ActionCodeURL.swift 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright 2023 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. /// This class will allow developers to easily extract information about out of band links.
  16. @objc(FIRActionCodeURL) open class ActionCodeURL: NSObject {
  17. /// Returns the API key from the link. nil, if not provided.
  18. @objc(APIKey) public let apiKey: String?
  19. /// Returns the mode of oob action.
  20. ///
  21. /// The property will be of `ActionCodeOperation` type.
  22. /// It will return `.unknown` if no oob action is provided.
  23. @objc public let operation: ActionCodeOperation
  24. /// Returns the email action code from the link. nil, if not provided.
  25. @objc public let code: String?
  26. /// Returns the continue URL from the link. nil, if not provided.
  27. @objc public let continueURL: URL?
  28. /// Returns the language code from the link. nil, if not provided.
  29. @objc public let languageCode: String?
  30. /// Construct an `ActionCodeURL` from an out of band link (e.g. email link).
  31. /// - Parameter link: The oob link string used to construct the action code URL.
  32. /// - Returns: The ActionCodeURL object constructed based on the oob link provided.
  33. @objc(actionCodeURLWithLink:) public init?(link: String) {
  34. var queryItems = ActionCodeURL.parseURL(link)
  35. if queryItems.count == 0 {
  36. let urlComponents = URLComponents(string: link)
  37. if let query = urlComponents?.query {
  38. queryItems = ActionCodeURL.parseURL(query)
  39. }
  40. }
  41. guard queryItems.count > 0 else {
  42. return nil
  43. }
  44. apiKey = queryItems["apiKey"]
  45. operation = ActionCodeInfo.actionCodeOperation(forRequestType: queryItems["mode"])
  46. code = queryItems["oobCode"]
  47. if let continueURL = queryItems["continueUrl"] {
  48. self.continueURL = URL(string: continueURL)
  49. } else {
  50. continueURL = nil
  51. }
  52. languageCode = queryItems["languageCode"]
  53. }
  54. class func parseURL(_ urlString: String) -> [String: String] {
  55. guard let linkURL = URLComponents(string: urlString)?.query else {
  56. return [:]
  57. }
  58. var queryItems: [String: String] = [:]
  59. let urlComponents = linkURL.components(separatedBy: "&")
  60. for component in urlComponents {
  61. let splitArray = component.split(separator: "=")
  62. if let queryItemKey = String(splitArray[0]).removingPercentEncoding,
  63. let queryItemValue = String(splitArray[1]).removingPercentEncoding {
  64. queryItems[queryItemKey] = queryItemValue
  65. }
  66. }
  67. return queryItems
  68. }
  69. }