diff --git a/SynchronyFinancial/Podfile.lock b/SynchronyFinancial/Podfile.lock index 92ee303..1f05592 100644 --- a/SynchronyFinancial/Podfile.lock +++ b/SynchronyFinancial/Podfile.lock @@ -1,16 +1,20 @@ PODS: + - Alamofire (4.7.3) - SwiftLint (0.27.0) DEPENDENCIES: + - Alamofire - SwiftLint SPEC REPOS: https://github.com/cocoapods/specs.git: + - Alamofire - SwiftLint SPEC CHECKSUMS: + Alamofire: c7287b6e5d7da964a70935e5db17046b7fde6568 SwiftLint: 3207c1faa2240bf8973b191820a116113cd11073 -PODFILE CHECKSUM: 4677f0f790934708825f5fcde561667ebefd2df5 +PODFILE CHECKSUM: 8390a2d9691b418a9cdf2f8053ba0a852a522b37 COCOAPODS: 1.5.3 diff --git a/SynchronyFinancial/Pods/Alamofire/LICENSE b/SynchronyFinancial/Pods/Alamofire/LICENSE new file mode 100644 index 0000000..2ec3cb1 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/SynchronyFinancial/Pods/Alamofire/README.md b/SynchronyFinancial/Pods/Alamofire/README.md new file mode 100644 index 0000000..0208252 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/README.md @@ -0,0 +1,242 @@ +![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/alamofire.png) + +[![Build Status](https://travis-ci.org/Alamofire/Alamofire.svg?branch=master)](https://travis-ci.org/Alamofire/Alamofire) +[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg)](https://img.shields.io/cocoapods/v/Alamofire.svg) +[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](https://alamofire.github.io/Alamofire) +[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat)](https://twitter.com/AlamofireSF) +[![Gitter](https://badges.gitter.im/Alamofire/Alamofire.svg)](https://gitter.im/Alamofire/Alamofire?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +Alamofire is an HTTP networking library written in Swift. + +- [Features](#features) +- [Component Libraries](#component-libraries) +- [Requirements](#requirements) +- [Migration Guides](#migration-guides) +- [Communication](#communication) +- [Installation](#installation) +- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md) + - **Intro -** [Making a Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#making-a-request), [Response Handling](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-handling), [Response Validation](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-validation), [Response Caching](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-caching) + - **HTTP -** [HTTP Methods](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods), [Parameter Encoding](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#parameter-encoding), [HTTP Headers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-headers), [Authentication](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#authentication) + - **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server) + - **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output) +- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md) + - **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-manager), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-delegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request) + - **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests) + - **Model Objects -** [Custom Response Serialization](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#custom-response-serialization) + - **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability) +- [Open Radars](#open-radars) +- [FAQ](#faq) +- [Credits](#credits) +- [Donations](#donations) +- [License](#license) + +## Features + +- [x] Chainable Request / Response Methods +- [x] URL / JSON / plist Parameter Encoding +- [x] Upload File / Data / Stream / MultipartFormData +- [x] Download File using Request or Resume Data +- [x] Authentication with URLCredential +- [x] HTTP Response Validation +- [x] Upload and Download Progress Closures with Progress +- [x] cURL Command Output +- [x] Dynamically Adapt and Retry Requests +- [x] TLS Certificate and Public Key Pinning +- [x] Network Reachability +- [x] Comprehensive Unit and Integration Test Coverage +- [x] [Complete Documentation](https://alamofire.github.io/Alamofire) + +## Component Libraries + +In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem. + +- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) - An image library including image response serializers, `UIImage` and `UIImageView` extensions, custom image filters, an auto-purging in-memory cache and a priority-based image downloading system. +- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) - Controls the visibility of the network activity indicator on iOS using Alamofire. It contains configurable delay timers to help mitigate flicker and can support `URLSession` instances not managed by Alamofire. + +## Requirements + +- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+ +- Xcode 8.3+ +- Swift 3.1+ + +## Migration Guides + +- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md) +- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md) +- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md) + +## Communication + +- If you **need help**, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire). (Tag 'alamofire') +- If you'd like to **ask a general question**, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire). +- If you **found a bug**, open an issue. +- If you **have a feature request**, open an issue. +- If you **want to contribute**, submit a pull request. + +## Installation + +### CocoaPods + +[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: + +```bash +$ gem install cocoapods +``` + +> CocoaPods 1.1+ is required to build Alamofire 4.0+. + +To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`: + +```ruby +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '10.0' +use_frameworks! + +target '' do + pod 'Alamofire', '~> 4.7' +end +``` + +Then, run the following command: + +```bash +$ pod install +``` + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. + +You can install Carthage with [Homebrew](https://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "Alamofire/Alamofire" ~> 4.7 +``` + +Run `carthage update` to build the framework and drag the built `Alamofire.framework` into your Xcode project. + +### Swift Package Manager + +The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Alamofire does support its use on supported platforms. + +Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`. + +#### Swift 3 + +```swift +dependencies: [ + .Package(url: "https://github.com/Alamofire/Alamofire.git", majorVersion: 4) +] +``` + +#### Swift 4 + +```swift +dependencies: [ + .package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.0.0") +] +``` + +### Manually + +If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually. + +#### Embedded Framework + +- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository: + + ```bash + $ git init + ``` + +- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command: + + ```bash + $ git submodule add https://github.com/Alamofire/Alamofire.git + ``` + +- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project. + + > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter. + +- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target. +- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar. +- In the tab bar at the top of that window, open the "General" panel. +- Click on the `+` button under the "Embedded Binaries" section. +- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder. + + > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`. + +- Select the top `Alamofire.framework` for iOS and the bottom one for OS X. + + > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as either `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS` or `Alamofire watchOS`. + +- And that's it! + + > The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device. + +## Open Radars + +The following radars have some effect on the current implementation of Alamofire. + +- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case +- `rdar://26870455` - Background URL Session Configurations do not work in the simulator +- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest` +- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+ + +## Resolved Radars + +The following radars have been resolved over time after being filed against the Alamofire project. + +- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage (Resolved on 9/1/17 in Xcode 9 beta 6). + +## FAQ + +### What's the origin of the name Alamofire? + +Alamofire is named after the [Alamo Fire flower](https://aggie-horticulture.tamu.edu/wildseed/alamofire.html), a hybrid variant of the Bluebonnet, the official state flower of Texas. + +### What logic belongs in a Router vs. a Request Adapter? + +Simple, static data such as paths, parameters and common headers belong in the `Router`. Dynamic data such as an `Authorization` header whose value can changed based on an authentication system belongs in a `RequestAdapter`. + +The reason the dynamic data MUST be placed into the `RequestAdapter` is to support retry operations. When a `Request` is retried, the original request is not rebuilt meaning the `Router` will not be called again. The `RequestAdapter` is called again allowing the dynamic data to be updated on the original request before retrying the `Request`. + +## Credits + +Alamofire is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). You can follow them on Twitter at [@AlamofireSF](https://twitter.com/AlamofireSF) for project updates and releases. + +### Security Disclosure + +If you believe you have identified a security vulnerability with Alamofire, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker. + +## Donations + +The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization. +Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax free. +Donating to the ASF will enable us to: + +- Pay our yearly legal fees to keep the non-profit in good status +- Pay for our mail servers to help us stay on top of all questions and security issues +- Potentially fund test servers to make it easier for us to test the edge cases +- Potentially fund developers to work on one of our projects full-time + +The community adoption of the ASF libraries has been amazing. +We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward. +With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members. +If you use any of our libraries for work, see if your employers would be interested in donating. +Any amount you can donate today to help us reach our goal would be greatly appreciated. + +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W34WPEE74APJQ) + +## License + +Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details. diff --git a/SynchronyFinancial/Pods/Alamofire/Source/AFError.swift b/SynchronyFinancial/Pods/Alamofire/Source/AFError.swift new file mode 100644 index 0000000..8b90d84 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/AFError.swift @@ -0,0 +1,460 @@ +// +// AFError.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with +/// their own associated reasons. +/// +/// - invalidURL: Returned when a `URLConvertible` type fails to create a valid `URL`. +/// - parameterEncodingFailed: Returned when a parameter encoding object throws an error during the encoding process. +/// - multipartEncodingFailed: Returned when some step in the multipart encoding process fails. +/// - responseValidationFailed: Returned when a `validate()` call fails. +/// - responseSerializationFailed: Returned when a response serializer encounters an error in the serialization process. +public enum AFError: Error { + /// The underlying reason the parameter encoding error occurred. + /// + /// - missingURL: The URL request did not have a URL to encode. + /// - jsonEncodingFailed: JSON serialization failed with an underlying system error during the + /// encoding process. + /// - propertyListEncodingFailed: Property list serialization failed with an underlying system error during + /// encoding process. + public enum ParameterEncodingFailureReason { + case missingURL + case jsonEncodingFailed(error: Error) + case propertyListEncodingFailed(error: Error) + } + + /// The underlying reason the multipart encoding error occurred. + /// + /// - bodyPartURLInvalid: The `fileURL` provided for reading an encodable body part isn't a + /// file URL. + /// - bodyPartFilenameInvalid: The filename of the `fileURL` provided has either an empty + /// `lastPathComponent` or `pathExtension. + /// - bodyPartFileNotReachable: The file at the `fileURL` provided was not reachable. + /// - bodyPartFileNotReachableWithError: Attempting to check the reachability of the `fileURL` provided threw + /// an error. + /// - bodyPartFileIsDirectory: The file at the `fileURL` provided is actually a directory. + /// - bodyPartFileSizeNotAvailable: The size of the file at the `fileURL` provided was not returned by + /// the system. + /// - bodyPartFileSizeQueryFailedWithError: The attempt to find the size of the file at the `fileURL` provided + /// threw an error. + /// - bodyPartInputStreamCreationFailed: An `InputStream` could not be created for the provided `fileURL`. + /// - outputStreamCreationFailed: An `OutputStream` could not be created when attempting to write the + /// encoded data to disk. + /// - outputStreamFileAlreadyExists: The encoded body data could not be writtent disk because a file + /// already exists at the provided `fileURL`. + /// - outputStreamURLInvalid: The `fileURL` provided for writing the encoded body data to disk is + /// not a file URL. + /// - outputStreamWriteFailed: The attempt to write the encoded body data to disk failed with an + /// underlying error. + /// - inputStreamReadFailed: The attempt to read an encoded body part `InputStream` failed with + /// underlying system error. + public enum MultipartEncodingFailureReason { + case bodyPartURLInvalid(url: URL) + case bodyPartFilenameInvalid(in: URL) + case bodyPartFileNotReachable(at: URL) + case bodyPartFileNotReachableWithError(atURL: URL, error: Error) + case bodyPartFileIsDirectory(at: URL) + case bodyPartFileSizeNotAvailable(at: URL) + case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error) + case bodyPartInputStreamCreationFailed(for: URL) + + case outputStreamCreationFailed(for: URL) + case outputStreamFileAlreadyExists(at: URL) + case outputStreamURLInvalid(url: URL) + case outputStreamWriteFailed(error: Error) + + case inputStreamReadFailed(error: Error) + } + + /// The underlying reason the response validation error occurred. + /// + /// - dataFileNil: The data file containing the server response did not exist. + /// - dataFileReadFailed: The data file containing the server response could not be read. + /// - missingContentType: The response did not contain a `Content-Type` and the `acceptableContentTypes` + /// provided did not contain wildcard type. + /// - unacceptableContentType: The response `Content-Type` did not match any type in the provided + /// `acceptableContentTypes`. + /// - unacceptableStatusCode: The response status code was not acceptable. + public enum ResponseValidationFailureReason { + case dataFileNil + case dataFileReadFailed(at: URL) + case missingContentType(acceptableContentTypes: [String]) + case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String) + case unacceptableStatusCode(code: Int) + } + + /// The underlying reason the response serialization error occurred. + /// + /// - inputDataNil: The server response contained no data. + /// - inputDataNilOrZeroLength: The server response contained no data or the data was zero length. + /// - inputFileNil: The file containing the server response did not exist. + /// - inputFileReadFailed: The file containing the server response could not be read. + /// - stringSerializationFailed: String serialization failed using the provided `String.Encoding`. + /// - jsonSerializationFailed: JSON serialization failed with an underlying system error. + /// - propertyListSerializationFailed: Property list serialization failed with an underlying system error. + public enum ResponseSerializationFailureReason { + case inputDataNil + case inputDataNilOrZeroLength + case inputFileNil + case inputFileReadFailed(at: URL) + case stringSerializationFailed(encoding: String.Encoding) + case jsonSerializationFailed(error: Error) + case propertyListSerializationFailed(error: Error) + } + + case invalidURL(url: URLConvertible) + case parameterEncodingFailed(reason: ParameterEncodingFailureReason) + case multipartEncodingFailed(reason: MultipartEncodingFailureReason) + case responseValidationFailed(reason: ResponseValidationFailureReason) + case responseSerializationFailed(reason: ResponseSerializationFailureReason) +} + +// MARK: - Adapt Error + +struct AdaptError: Error { + let error: Error +} + +extension Error { + var underlyingAdaptError: Error? { return (self as? AdaptError)?.error } +} + +// MARK: - Error Booleans + +extension AFError { + /// Returns whether the AFError is an invalid URL error. + public var isInvalidURLError: Bool { + if case .invalidURL = self { return true } + return false + } + + /// Returns whether the AFError is a parameter encoding error. When `true`, the `underlyingError` property will + /// contain the associated value. + public var isParameterEncodingError: Bool { + if case .parameterEncodingFailed = self { return true } + return false + } + + /// Returns whether the AFError is a multipart encoding error. When `true`, the `url` and `underlyingError` properties + /// will contain the associated values. + public var isMultipartEncodingError: Bool { + if case .multipartEncodingFailed = self { return true } + return false + } + + /// Returns whether the `AFError` is a response validation error. When `true`, the `acceptableContentTypes`, + /// `responseContentType`, and `responseCode` properties will contain the associated values. + public var isResponseValidationError: Bool { + if case .responseValidationFailed = self { return true } + return false + } + + /// Returns whether the `AFError` is a response serialization error. When `true`, the `failedStringEncoding` and + /// `underlyingError` properties will contain the associated values. + public var isResponseSerializationError: Bool { + if case .responseSerializationFailed = self { return true } + return false + } +} + +// MARK: - Convenience Properties + +extension AFError { + /// The `URLConvertible` associated with the error. + public var urlConvertible: URLConvertible? { + switch self { + case .invalidURL(let url): + return url + default: + return nil + } + } + + /// The `URL` associated with the error. + public var url: URL? { + switch self { + case .multipartEncodingFailed(let reason): + return reason.url + default: + return nil + } + } + + /// The `Error` returned by a system framework associated with a `.parameterEncodingFailed`, + /// `.multipartEncodingFailed` or `.responseSerializationFailed` error. + public var underlyingError: Error? { + switch self { + case .parameterEncodingFailed(let reason): + return reason.underlyingError + case .multipartEncodingFailed(let reason): + return reason.underlyingError + case .responseSerializationFailed(let reason): + return reason.underlyingError + default: + return nil + } + } + + /// The acceptable `Content-Type`s of a `.responseValidationFailed` error. + public var acceptableContentTypes: [String]? { + switch self { + case .responseValidationFailed(let reason): + return reason.acceptableContentTypes + default: + return nil + } + } + + /// The response `Content-Type` of a `.responseValidationFailed` error. + public var responseContentType: String? { + switch self { + case .responseValidationFailed(let reason): + return reason.responseContentType + default: + return nil + } + } + + /// The response code of a `.responseValidationFailed` error. + public var responseCode: Int? { + switch self { + case .responseValidationFailed(let reason): + return reason.responseCode + default: + return nil + } + } + + /// The `String.Encoding` associated with a failed `.stringResponse()` call. + public var failedStringEncoding: String.Encoding? { + switch self { + case .responseSerializationFailed(let reason): + return reason.failedStringEncoding + default: + return nil + } + } +} + +extension AFError.ParameterEncodingFailureReason { + var underlyingError: Error? { + switch self { + case .jsonEncodingFailed(let error), .propertyListEncodingFailed(let error): + return error + default: + return nil + } + } +} + +extension AFError.MultipartEncodingFailureReason { + var url: URL? { + switch self { + case .bodyPartURLInvalid(let url), .bodyPartFilenameInvalid(let url), .bodyPartFileNotReachable(let url), + .bodyPartFileIsDirectory(let url), .bodyPartFileSizeNotAvailable(let url), + .bodyPartInputStreamCreationFailed(let url), .outputStreamCreationFailed(let url), + .outputStreamFileAlreadyExists(let url), .outputStreamURLInvalid(let url), + .bodyPartFileNotReachableWithError(let url, _), .bodyPartFileSizeQueryFailedWithError(let url, _): + return url + default: + return nil + } + } + + var underlyingError: Error? { + switch self { + case .bodyPartFileNotReachableWithError(_, let error), .bodyPartFileSizeQueryFailedWithError(_, let error), + .outputStreamWriteFailed(let error), .inputStreamReadFailed(let error): + return error + default: + return nil + } + } +} + +extension AFError.ResponseValidationFailureReason { + var acceptableContentTypes: [String]? { + switch self { + case .missingContentType(let types), .unacceptableContentType(let types, _): + return types + default: + return nil + } + } + + var responseContentType: String? { + switch self { + case .unacceptableContentType(_, let responseType): + return responseType + default: + return nil + } + } + + var responseCode: Int? { + switch self { + case .unacceptableStatusCode(let code): + return code + default: + return nil + } + } +} + +extension AFError.ResponseSerializationFailureReason { + var failedStringEncoding: String.Encoding? { + switch self { + case .stringSerializationFailed(let encoding): + return encoding + default: + return nil + } + } + + var underlyingError: Error? { + switch self { + case .jsonSerializationFailed(let error), .propertyListSerializationFailed(let error): + return error + default: + return nil + } + } +} + +// MARK: - Error Descriptions + +extension AFError: LocalizedError { + public var errorDescription: String? { + switch self { + case .invalidURL(let url): + return "URL is not valid: \(url)" + case .parameterEncodingFailed(let reason): + return reason.localizedDescription + case .multipartEncodingFailed(let reason): + return reason.localizedDescription + case .responseValidationFailed(let reason): + return reason.localizedDescription + case .responseSerializationFailed(let reason): + return reason.localizedDescription + } + } +} + +extension AFError.ParameterEncodingFailureReason { + var localizedDescription: String { + switch self { + case .missingURL: + return "URL request to encode was missing a URL" + case .jsonEncodingFailed(let error): + return "JSON could not be encoded because of error:\n\(error.localizedDescription)" + case .propertyListEncodingFailed(let error): + return "PropertyList could not be encoded because of error:\n\(error.localizedDescription)" + } + } +} + +extension AFError.MultipartEncodingFailureReason { + var localizedDescription: String { + switch self { + case .bodyPartURLInvalid(let url): + return "The URL provided is not a file URL: \(url)" + case .bodyPartFilenameInvalid(let url): + return "The URL provided does not have a valid filename: \(url)" + case .bodyPartFileNotReachable(let url): + return "The URL provided is not reachable: \(url)" + case .bodyPartFileNotReachableWithError(let url, let error): + return ( + "The system returned an error while checking the provided URL for " + + "reachability.\nURL: \(url)\nError: \(error)" + ) + case .bodyPartFileIsDirectory(let url): + return "The URL provided is a directory: \(url)" + case .bodyPartFileSizeNotAvailable(let url): + return "Could not fetch the file size from the provided URL: \(url)" + case .bodyPartFileSizeQueryFailedWithError(let url, let error): + return ( + "The system returned an error while attempting to fetch the file size from the " + + "provided URL.\nURL: \(url)\nError: \(error)" + ) + case .bodyPartInputStreamCreationFailed(let url): + return "Failed to create an InputStream for the provided URL: \(url)" + case .outputStreamCreationFailed(let url): + return "Failed to create an OutputStream for URL: \(url)" + case .outputStreamFileAlreadyExists(let url): + return "A file already exists at the provided URL: \(url)" + case .outputStreamURLInvalid(let url): + return "The provided OutputStream URL is invalid: \(url)" + case .outputStreamWriteFailed(let error): + return "OutputStream write failed with error: \(error)" + case .inputStreamReadFailed(let error): + return "InputStream read failed with error: \(error)" + } + } +} + +extension AFError.ResponseSerializationFailureReason { + var localizedDescription: String { + switch self { + case .inputDataNil: + return "Response could not be serialized, input data was nil." + case .inputDataNilOrZeroLength: + return "Response could not be serialized, input data was nil or zero length." + case .inputFileNil: + return "Response could not be serialized, input file was nil." + case .inputFileReadFailed(let url): + return "Response could not be serialized, input file could not be read: \(url)." + case .stringSerializationFailed(let encoding): + return "String could not be serialized with encoding: \(encoding)." + case .jsonSerializationFailed(let error): + return "JSON could not be serialized because of error:\n\(error.localizedDescription)" + case .propertyListSerializationFailed(let error): + return "PropertyList could not be serialized because of error:\n\(error.localizedDescription)" + } + } +} + +extension AFError.ResponseValidationFailureReason { + var localizedDescription: String { + switch self { + case .dataFileNil: + return "Response could not be validated, data file was nil." + case .dataFileReadFailed(let url): + return "Response could not be validated, data file could not be read: \(url)." + case .missingContentType(let types): + return ( + "Response Content-Type was missing and acceptable content types " + + "(\(types.joined(separator: ","))) do not match \"*/*\"." + ) + case .unacceptableContentType(let acceptableTypes, let responseType): + return ( + "Response Content-Type \"\(responseType)\" does not match any acceptable types: " + + "\(acceptableTypes.joined(separator: ","))." + ) + case .unacceptableStatusCode(let code): + return "Response status code was unacceptable: \(code)." + } + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Alamofire.swift b/SynchronyFinancial/Pods/Alamofire/Source/Alamofire.swift new file mode 100644 index 0000000..2fcc05c --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Alamofire.swift @@ -0,0 +1,465 @@ +// +// Alamofire.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Types adopting the `URLConvertible` protocol can be used to construct URLs, which are then used to construct +/// URL requests. +public protocol URLConvertible { + /// Returns a URL that conforms to RFC 2396 or throws an `Error`. + /// + /// - throws: An `Error` if the type cannot be converted to a `URL`. + /// + /// - returns: A URL or throws an `Error`. + func asURL() throws -> URL +} + +extension String: URLConvertible { + /// Returns a URL if `self` represents a valid URL string that conforms to RFC 2396 or throws an `AFError`. + /// + /// - throws: An `AFError.invalidURL` if `self` is not a valid URL string. + /// + /// - returns: A URL or throws an `AFError`. + public func asURL() throws -> URL { + guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) } + return url + } +} + +extension URL: URLConvertible { + /// Returns self. + public func asURL() throws -> URL { return self } +} + +extension URLComponents: URLConvertible { + /// Returns a URL if `url` is not nil, otherwise throws an `Error`. + /// + /// - throws: An `AFError.invalidURL` if `url` is `nil`. + /// + /// - returns: A URL or throws an `AFError`. + public func asURL() throws -> URL { + guard let url = url else { throw AFError.invalidURL(url: self) } + return url + } +} + +// MARK: - + +/// Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests. +public protocol URLRequestConvertible { + /// Returns a URL request or throws if an `Error` was encountered. + /// + /// - throws: An `Error` if the underlying `URLRequest` is `nil`. + /// + /// - returns: A URL request. + func asURLRequest() throws -> URLRequest +} + +extension URLRequestConvertible { + /// The URL request. + public var urlRequest: URLRequest? { return try? asURLRequest() } +} + +extension URLRequest: URLRequestConvertible { + /// Returns a URL request or throws if an `Error` was encountered. + public func asURLRequest() throws -> URLRequest { return self } +} + +// MARK: - + +extension URLRequest { + /// Creates an instance with the specified `method`, `urlString` and `headers`. + /// + /// - parameter url: The URL. + /// - parameter method: The HTTP method. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The new `URLRequest` instance. + public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws { + let url = try url.asURL() + + self.init(url: url) + + httpMethod = method.rawValue + + if let headers = headers { + for (headerField, headerValue) in headers { + setValue(headerValue, forHTTPHeaderField: headerField) + } + } + } + + func adapt(using adapter: RequestAdapter?) throws -> URLRequest { + guard let adapter = adapter else { return self } + return try adapter.adapt(self) + } +} + +// MARK: - Data Request + +/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of the specified `url`, +/// `method`, `parameters`, `encoding` and `headers`. +/// +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.get` by default. +/// - parameter parameters: The parameters. `nil` by default. +/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `DataRequest`. +@discardableResult +public func request( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil) + -> DataRequest +{ + return SessionManager.default.request( + url, + method: method, + parameters: parameters, + encoding: encoding, + headers: headers + ) +} + +/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of a URL based on the +/// specified `urlRequest`. +/// +/// - parameter urlRequest: The URL request +/// +/// - returns: The created `DataRequest`. +@discardableResult +public func request(_ urlRequest: URLRequestConvertible) -> DataRequest { + return SessionManager.default.request(urlRequest) +} + +// MARK: - Download Request + +// MARK: URL Request + +/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of the specified `url`, +/// `method`, `parameters`, `encoding`, `headers` and save them to the `destination`. +/// +/// If `destination` is not specified, the contents will remain in the temporary location determined by the +/// underlying URL session. +/// +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.get` by default. +/// - parameter parameters: The parameters. `nil` by default. +/// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. +/// +/// - returns: The created `DownloadRequest`. +@discardableResult +public func download( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest +{ + return SessionManager.default.download( + url, + method: method, + parameters: parameters, + encoding: encoding, + headers: headers, + to: destination + ) +} + +/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of a URL based on the +/// specified `urlRequest` and save them to the `destination`. +/// +/// If `destination` is not specified, the contents will remain in the temporary location determined by the +/// underlying URL session. +/// +/// - parameter urlRequest: The URL request. +/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. +/// +/// - returns: The created `DownloadRequest`. +@discardableResult +public func download( + _ urlRequest: URLRequestConvertible, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest +{ + return SessionManager.default.download(urlRequest, to: destination) +} + +// MARK: Resume Data + +/// Creates a `DownloadRequest` using the default `SessionManager` from the `resumeData` produced from a +/// previous request cancellation to retrieve the contents of the original request and save them to the `destination`. +/// +/// If `destination` is not specified, the contents will remain in the temporary location determined by the +/// underlying URL session. +/// +/// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken +/// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the +/// data is written incorrectly and will always fail to resume the download. For more information about the bug and +/// possible workarounds, please refer to the following Stack Overflow post: +/// +/// - http://stackoverflow.com/a/39347461/1342462 +/// +/// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask` +/// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for additional +/// information. +/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. +/// +/// - returns: The created `DownloadRequest`. +@discardableResult +public func download( + resumingWith resumeData: Data, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest +{ + return SessionManager.default.download(resumingWith: resumeData, to: destination) +} + +// MARK: - Upload Request + +// MARK: File + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers` +/// for uploading the `file`. +/// +/// - parameter file: The file to upload. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload( + _ fileURL: URL, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest +{ + return SessionManager.default.upload(fileURL, to: url, method: method, headers: headers) +} + +/// Creates a `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for +/// uploading the `file`. +/// +/// - parameter file: The file to upload. +/// - parameter urlRequest: The URL request. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest { + return SessionManager.default.upload(fileURL, with: urlRequest) +} + +// MARK: Data + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers` +/// for uploading the `data`. +/// +/// - parameter data: The data to upload. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload( + _ data: Data, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest +{ + return SessionManager.default.upload(data, to: url, method: method, headers: headers) +} + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for +/// uploading the `data`. +/// +/// - parameter data: The data to upload. +/// - parameter urlRequest: The URL request. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest { + return SessionManager.default.upload(data, with: urlRequest) +} + +// MARK: InputStream + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers` +/// for uploading the `stream`. +/// +/// - parameter stream: The stream to upload. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload( + _ stream: InputStream, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest +{ + return SessionManager.default.upload(stream, to: url, method: method, headers: headers) +} + +/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for +/// uploading the `stream`. +/// +/// - parameter urlRequest: The URL request. +/// - parameter stream: The stream to upload. +/// +/// - returns: The created `UploadRequest`. +@discardableResult +public func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest { + return SessionManager.default.upload(stream, with: urlRequest) +} + +// MARK: MultipartFormData + +/// Encodes `multipartFormData` using `encodingMemoryThreshold` with the default `SessionManager` and calls +/// `encodingCompletion` with new `UploadRequest` using the `url`, `method` and `headers`. +/// +/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative +/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most +/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to +/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory +/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be +/// used for larger payloads such as video content. +/// +/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory +/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, +/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk +/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding +/// technique was used. +/// +/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. +/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. +/// `multipartFormDataEncodingMemoryThreshold` by default. +/// - parameter url: The URL. +/// - parameter method: The HTTP method. `.post` by default. +/// - parameter headers: The HTTP headers. `nil` by default. +/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. +public func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil, + encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?) +{ + return SessionManager.default.upload( + multipartFormData: multipartFormData, + usingThreshold: encodingMemoryThreshold, + to: url, + method: method, + headers: headers, + encodingCompletion: encodingCompletion + ) +} + +/// Encodes `multipartFormData` using `encodingMemoryThreshold` and the default `SessionManager` and +/// calls `encodingCompletion` with new `UploadRequest` using the `urlRequest`. +/// +/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative +/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most +/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to +/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory +/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be +/// used for larger payloads such as video content. +/// +/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory +/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, +/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk +/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding +/// technique was used. +/// +/// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. +/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. +/// `multipartFormDataEncodingMemoryThreshold` by default. +/// - parameter urlRequest: The URL request. +/// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. +public func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + with urlRequest: URLRequestConvertible, + encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?) +{ + return SessionManager.default.upload( + multipartFormData: multipartFormData, + usingThreshold: encodingMemoryThreshold, + with: urlRequest, + encodingCompletion: encodingCompletion + ) +} + +#if !os(watchOS) + +// MARK: - Stream Request + +// MARK: Hostname and Port + +/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `hostname` +/// and `port`. +/// +/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. +/// +/// - parameter hostName: The hostname of the server to connect to. +/// - parameter port: The port of the server to connect to. +/// +/// - returns: The created `StreamRequest`. +@discardableResult +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +public func stream(withHostName hostName: String, port: Int) -> StreamRequest { + return SessionManager.default.stream(withHostName: hostName, port: port) +} + +// MARK: NetService + +/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `netService`. +/// +/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. +/// +/// - parameter netService: The net service used to identify the endpoint. +/// +/// - returns: The created `StreamRequest`. +@discardableResult +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +public func stream(with netService: NetService) -> StreamRequest { + return SessionManager.default.stream(with: netService) +} + +#endif diff --git a/SynchronyFinancial/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift b/SynchronyFinancial/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift new file mode 100644 index 0000000..dea3ebc --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift @@ -0,0 +1,37 @@ +// +// DispatchQueue+Alamofire.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Dispatch +import Foundation + +extension DispatchQueue { + static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) } + static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) } + static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) } + static var background: DispatchQueue { return DispatchQueue.global(qos: .background) } + + func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) { + asyncAfter(deadline: .now() + delay, execute: closure) + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/MultipartFormData.swift b/SynchronyFinancial/Pods/Alamofire/Source/MultipartFormData.swift new file mode 100644 index 0000000..057e68b --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/MultipartFormData.swift @@ -0,0 +1,580 @@ +// +// MultipartFormData.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +#if os(iOS) || os(watchOS) || os(tvOS) +import MobileCoreServices +#elseif os(macOS) +import CoreServices +#endif + +/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode +/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead +/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the +/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for +/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset. +/// +/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well +/// and the w3 form documentation. +/// +/// - https://www.ietf.org/rfc/rfc2388.txt +/// - https://www.ietf.org/rfc/rfc2045.txt +/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13 +open class MultipartFormData { + + // MARK: - Helper Types + + struct EncodingCharacters { + static let crlf = "\r\n" + } + + struct BoundaryGenerator { + enum BoundaryType { + case initial, encapsulated, final + } + + static func randomBoundary() -> String { + return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random()) + } + + static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data { + let boundaryText: String + + switch boundaryType { + case .initial: + boundaryText = "--\(boundary)\(EncodingCharacters.crlf)" + case .encapsulated: + boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)" + case .final: + boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)" + } + + return boundaryText.data(using: String.Encoding.utf8, allowLossyConversion: false)! + } + } + + class BodyPart { + let headers: HTTPHeaders + let bodyStream: InputStream + let bodyContentLength: UInt64 + var hasInitialBoundary = false + var hasFinalBoundary = false + + init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) { + self.headers = headers + self.bodyStream = bodyStream + self.bodyContentLength = bodyContentLength + } + } + + // MARK: - Properties + + /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`. + open lazy var contentType: String = "multipart/form-data; boundary=\(self.boundary)" + + /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries. + public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } } + + /// The boundary used to separate the body parts in the encoded form data. + public let boundary: String + + private var bodyParts: [BodyPart] + private var bodyPartError: AFError? + private let streamBufferSize: Int + + // MARK: - Lifecycle + + /// Creates a multipart form data object. + /// + /// - returns: The multipart form data object. + public init() { + self.boundary = BoundaryGenerator.randomBoundary() + self.bodyParts = [] + + /// + /// The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more + /// information, please refer to the following article: + /// - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html + /// + + self.streamBufferSize = 1024 + } + + // MARK: - Body Parts + + /// Creates a body part from the data and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}` (HTTP Header) + /// - Encoded data + /// - Multipart form boundary + /// + /// - parameter data: The data to encode into the multipart form data. + /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. + public func append(_ data: Data, withName name: String) { + let headers = contentHeaders(withName: name) + let stream = InputStream(data: data) + let length = UInt64(data.count) + + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part from the data and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}` (HTTP Header) + /// - `Content-Type: #{generated mimeType}` (HTTP Header) + /// - Encoded data + /// - Multipart form boundary + /// + /// - parameter data: The data to encode into the multipart form data. + /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the data content type in the `Content-Type` HTTP header. + public func append(_ data: Data, withName name: String, mimeType: String) { + let headers = contentHeaders(withName: name, mimeType: mimeType) + let stream = InputStream(data: data) + let length = UInt64(data.count) + + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part from the data and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header) + /// - `Content-Type: #{mimeType}` (HTTP Header) + /// - Encoded file data + /// - Multipart form boundary + /// + /// - parameter data: The data to encode into the multipart form data. + /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. + /// - parameter fileName: The filename to associate with the data in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header. + public func append(_ data: Data, withName name: String, fileName: String, mimeType: String) { + let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType) + let stream = InputStream(data: data) + let length = UInt64(data.count) + + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part from the file and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header) + /// - `Content-Type: #{generated mimeType}` (HTTP Header) + /// - Encoded file data + /// - Multipart form boundary + /// + /// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the + /// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the + /// system associated MIME type. + /// + /// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data. + /// - parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header. + public func append(_ fileURL: URL, withName name: String) { + let fileName = fileURL.lastPathComponent + let pathExtension = fileURL.pathExtension + + if !fileName.isEmpty && !pathExtension.isEmpty { + let mime = mimeType(forPathExtension: pathExtension) + append(fileURL, withName: name, fileName: fileName, mimeType: mime) + } else { + setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL)) + } + } + + /// Creates a body part from the file and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header) + /// - Content-Type: #{mimeType} (HTTP Header) + /// - Encoded file data + /// - Multipart form boundary + /// + /// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data. + /// - parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header. + /// - parameter fileName: The filename to associate with the file content in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the file content in the `Content-Type` HTTP header. + public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) { + let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType) + + //============================================================ + // Check 1 - is file URL? + //============================================================ + + guard fileURL.isFileURL else { + setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL)) + return + } + + //============================================================ + // Check 2 - is file URL reachable? + //============================================================ + + do { + let isReachable = try fileURL.checkPromisedItemIsReachable() + guard isReachable else { + setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL)) + return + } + } catch { + setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error)) + return + } + + //============================================================ + // Check 3 - is file URL a directory? + //============================================================ + + var isDirectory: ObjCBool = false + let path = fileURL.path + + guard FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else { + setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL)) + return + } + + //============================================================ + // Check 4 - can the file size be extracted? + //============================================================ + + let bodyContentLength: UInt64 + + do { + guard let fileSize = try FileManager.default.attributesOfItem(atPath: path)[.size] as? NSNumber else { + setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL)) + return + } + + bodyContentLength = fileSize.uint64Value + } + catch { + setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error)) + return + } + + //============================================================ + // Check 5 - can a stream be created from file URL? + //============================================================ + + guard let stream = InputStream(url: fileURL) else { + setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL)) + return + } + + append(stream, withLength: bodyContentLength, headers: headers) + } + + /// Creates a body part from the stream and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header) + /// - `Content-Type: #{mimeType}` (HTTP Header) + /// - Encoded stream data + /// - Multipart form boundary + /// + /// - parameter stream: The input stream to encode in the multipart form data. + /// - parameter length: The content length of the stream. + /// - parameter name: The name to associate with the stream content in the `Content-Disposition` HTTP header. + /// - parameter fileName: The filename to associate with the stream content in the `Content-Disposition` HTTP header. + /// - parameter mimeType: The MIME type to associate with the stream content in the `Content-Type` HTTP header. + public func append( + _ stream: InputStream, + withLength length: UInt64, + name: String, + fileName: String, + mimeType: String) + { + let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType) + append(stream, withLength: length, headers: headers) + } + + /// Creates a body part with the headers, stream and length and appends it to the multipart form data object. + /// + /// The body part data will be encoded using the following format: + /// + /// - HTTP headers + /// - Encoded stream data + /// - Multipart form boundary + /// + /// - parameter stream: The input stream to encode in the multipart form data. + /// - parameter length: The content length of the stream. + /// - parameter headers: The HTTP headers for the body part. + public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) { + let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length) + bodyParts.append(bodyPart) + } + + // MARK: - Data Encoding + + /// Encodes all the appended body parts into a single `Data` value. + /// + /// It is important to note that this method will load all the appended body parts into memory all at the same + /// time. This method should only be used when the encoded data will have a small memory footprint. For large data + /// cases, please use the `writeEncodedDataToDisk(fileURL:completionHandler:)` method. + /// + /// - throws: An `AFError` if encoding encounters an error. + /// + /// - returns: The encoded `Data` if encoding is successful. + public func encode() throws -> Data { + if let bodyPartError = bodyPartError { + throw bodyPartError + } + + var encoded = Data() + + bodyParts.first?.hasInitialBoundary = true + bodyParts.last?.hasFinalBoundary = true + + for bodyPart in bodyParts { + let encodedData = try encode(bodyPart) + encoded.append(encodedData) + } + + return encoded + } + + /// Writes the appended body parts into the given file URL. + /// + /// This process is facilitated by reading and writing with input and output streams, respectively. Thus, + /// this approach is very memory efficient and should be used for large body part data. + /// + /// - parameter fileURL: The file URL to write the multipart form data into. + /// + /// - throws: An `AFError` if encoding encounters an error. + public func writeEncodedData(to fileURL: URL) throws { + if let bodyPartError = bodyPartError { + throw bodyPartError + } + + if FileManager.default.fileExists(atPath: fileURL.path) { + throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL)) + } else if !fileURL.isFileURL { + throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL)) + } + + guard let outputStream = OutputStream(url: fileURL, append: false) else { + throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL)) + } + + outputStream.open() + defer { outputStream.close() } + + self.bodyParts.first?.hasInitialBoundary = true + self.bodyParts.last?.hasFinalBoundary = true + + for bodyPart in self.bodyParts { + try write(bodyPart, to: outputStream) + } + } + + // MARK: - Private - Body Part Encoding + + private func encode(_ bodyPart: BodyPart) throws -> Data { + var encoded = Data() + + let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData() + encoded.append(initialData) + + let headerData = encodeHeaders(for: bodyPart) + encoded.append(headerData) + + let bodyStreamData = try encodeBodyStream(for: bodyPart) + encoded.append(bodyStreamData) + + if bodyPart.hasFinalBoundary { + encoded.append(finalBoundaryData()) + } + + return encoded + } + + private func encodeHeaders(for bodyPart: BodyPart) -> Data { + var headerText = "" + + for (key, value) in bodyPart.headers { + headerText += "\(key): \(value)\(EncodingCharacters.crlf)" + } + headerText += EncodingCharacters.crlf + + return headerText.data(using: String.Encoding.utf8, allowLossyConversion: false)! + } + + private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data { + let inputStream = bodyPart.bodyStream + inputStream.open() + defer { inputStream.close() } + + var encoded = Data() + + while inputStream.hasBytesAvailable { + var buffer = [UInt8](repeating: 0, count: streamBufferSize) + let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize) + + if let error = inputStream.streamError { + throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error)) + } + + if bytesRead > 0 { + encoded.append(buffer, count: bytesRead) + } else { + break + } + } + + return encoded + } + + // MARK: - Private - Writing Body Part to Output Stream + + private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws { + try writeInitialBoundaryData(for: bodyPart, to: outputStream) + try writeHeaderData(for: bodyPart, to: outputStream) + try writeBodyStream(for: bodyPart, to: outputStream) + try writeFinalBoundaryData(for: bodyPart, to: outputStream) + } + + private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws { + let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData() + return try write(initialData, to: outputStream) + } + + private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws { + let headerData = encodeHeaders(for: bodyPart) + return try write(headerData, to: outputStream) + } + + private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws { + let inputStream = bodyPart.bodyStream + + inputStream.open() + defer { inputStream.close() } + + while inputStream.hasBytesAvailable { + var buffer = [UInt8](repeating: 0, count: streamBufferSize) + let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize) + + if let streamError = inputStream.streamError { + throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError)) + } + + if bytesRead > 0 { + if buffer.count != bytesRead { + buffer = Array(buffer[0.. 0, outputStream.hasSpaceAvailable { + let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite) + + if let error = outputStream.streamError { + throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error)) + } + + bytesToWrite -= bytesWritten + + if bytesToWrite > 0 { + buffer = Array(buffer[bytesWritten.. String { + if + let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(), + let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue() + { + return contentType as String + } + + return "application/octet-stream" + } + + // MARK: - Private - Content Headers + + private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> [String: String] { + var disposition = "form-data; name=\"\(name)\"" + if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" } + + var headers = ["Content-Disposition": disposition] + if let mimeType = mimeType { headers["Content-Type"] = mimeType } + + return headers + } + + // MARK: - Private - Boundary Encoding + + private func initialBoundaryData() -> Data { + return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary) + } + + private func encapsulatedBoundaryData() -> Data { + return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary) + } + + private func finalBoundaryData() -> Data { + return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary) + } + + // MARK: - Private - Errors + + private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) { + guard bodyPartError == nil else { return } + bodyPartError = AFError.multipartEncodingFailed(reason: reason) + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/NetworkReachabilityManager.swift b/SynchronyFinancial/Pods/Alamofire/Source/NetworkReachabilityManager.swift new file mode 100644 index 0000000..3ff2e7f --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/NetworkReachabilityManager.swift @@ -0,0 +1,233 @@ +// +// NetworkReachabilityManager.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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. +// + +#if !os(watchOS) + +import Foundation +import SystemConfiguration + +/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and +/// WiFi network interfaces. +/// +/// Reachability can be used to determine background information about why a network operation failed, or to retry +/// network requests when a connection is established. It should not be used to prevent a user from initiating a network +/// request, as it's possible that an initial request may be required to establish reachability. +open class NetworkReachabilityManager { + /// Defines the various states of network reachability. + /// + /// - unknown: It is unknown whether the network is reachable. + /// - notReachable: The network is not reachable. + /// - reachable: The network is reachable. + public enum NetworkReachabilityStatus { + case unknown + case notReachable + case reachable(ConnectionType) + } + + /// Defines the various connection types detected by reachability flags. + /// + /// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi. + /// - wwan: The connection type is a WWAN connection. + public enum ConnectionType { + case ethernetOrWiFi + case wwan + } + + /// A closure executed when the network reachability status changes. The closure takes a single argument: the + /// network reachability status. + public typealias Listener = (NetworkReachabilityStatus) -> Void + + // MARK: - Properties + + /// Whether the network is currently reachable. + open var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi } + + /// Whether the network is currently reachable over the WWAN interface. + open var isReachableOnWWAN: Bool { return networkReachabilityStatus == .reachable(.wwan) } + + /// Whether the network is currently reachable over Ethernet or WiFi interface. + open var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .reachable(.ethernetOrWiFi) } + + /// The current network reachability status. + open var networkReachabilityStatus: NetworkReachabilityStatus { + guard let flags = self.flags else { return .unknown } + return networkReachabilityStatusForFlags(flags) + } + + /// The dispatch queue to execute the `listener` closure on. + open var listenerQueue: DispatchQueue = DispatchQueue.main + + /// A closure executed when the network reachability status changes. + open var listener: Listener? + + open var flags: SCNetworkReachabilityFlags? { + var flags = SCNetworkReachabilityFlags() + + if SCNetworkReachabilityGetFlags(reachability, &flags) { + return flags + } + + return nil + } + + private let reachability: SCNetworkReachability + open var previousFlags: SCNetworkReachabilityFlags + + // MARK: - Initialization + + /// Creates a `NetworkReachabilityManager` instance with the specified host. + /// + /// - parameter host: The host used to evaluate network reachability. + /// + /// - returns: The new `NetworkReachabilityManager` instance. + public convenience init?(host: String) { + guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil } + self.init(reachability: reachability) + } + + /// Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0. + /// + /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing + /// status of the device, both IPv4 and IPv6. + /// + /// - returns: The new `NetworkReachabilityManager` instance. + public convenience init?() { + var address = sockaddr_in() + address.sin_len = UInt8(MemoryLayout.size) + address.sin_family = sa_family_t(AF_INET) + + guard let reachability = withUnsafePointer(to: &address, { pointer in + return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout.size) { + return SCNetworkReachabilityCreateWithAddress(nil, $0) + } + }) else { return nil } + + self.init(reachability: reachability) + } + + private init(reachability: SCNetworkReachability) { + self.reachability = reachability + self.previousFlags = SCNetworkReachabilityFlags() + } + + deinit { + stopListening() + } + + // MARK: - Listening + + /// Starts listening for changes in network reachability status. + /// + /// - returns: `true` if listening was started successfully, `false` otherwise. + @discardableResult + open func startListening() -> Bool { + var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) + context.info = Unmanaged.passUnretained(self).toOpaque() + + let callbackEnabled = SCNetworkReachabilitySetCallback( + reachability, + { (_, flags, info) in + let reachability = Unmanaged.fromOpaque(info!).takeUnretainedValue() + reachability.notifyListener(flags) + }, + &context + ) + + let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue) + + listenerQueue.async { + self.previousFlags = SCNetworkReachabilityFlags() + self.notifyListener(self.flags ?? SCNetworkReachabilityFlags()) + } + + return callbackEnabled && queueEnabled + } + + /// Stops listening for changes in network reachability status. + open func stopListening() { + SCNetworkReachabilitySetCallback(reachability, nil, nil) + SCNetworkReachabilitySetDispatchQueue(reachability, nil) + } + + // MARK: - Internal - Listener Notification + + func notifyListener(_ flags: SCNetworkReachabilityFlags) { + guard previousFlags != flags else { return } + previousFlags = flags + + listener?(networkReachabilityStatusForFlags(flags)) + } + + // MARK: - Internal - Network Reachability Status + + func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus { + guard isNetworkReachable(with: flags) else { return .notReachable } + + var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi) + + #if os(iOS) + if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) } + #endif + + return networkStatus + } + + func isNetworkReachable(with flags: SCNetworkReachabilityFlags) -> Bool { + let isReachable = flags.contains(.reachable) + let needsConnection = flags.contains(.connectionRequired) + let canConnectAutomatically = flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) + let canConnectWithoutUserInteraction = canConnectAutomatically && !flags.contains(.interventionRequired) + + return isReachable && (!needsConnection || canConnectWithoutUserInteraction) + } +} + +// MARK: - + +extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {} + +/// Returns whether the two network reachability status values are equal. +/// +/// - parameter lhs: The left-hand side value to compare. +/// - parameter rhs: The right-hand side value to compare. +/// +/// - returns: `true` if the two values are equal, `false` otherwise. +public func ==( + lhs: NetworkReachabilityManager.NetworkReachabilityStatus, + rhs: NetworkReachabilityManager.NetworkReachabilityStatus) + -> Bool +{ + switch (lhs, rhs) { + case (.unknown, .unknown): + return true + case (.notReachable, .notReachable): + return true + case let (.reachable(lhsConnectionType), .reachable(rhsConnectionType)): + return lhsConnectionType == rhsConnectionType + default: + return false + } +} + +#endif diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Notifications.swift b/SynchronyFinancial/Pods/Alamofire/Source/Notifications.swift new file mode 100644 index 0000000..e1b6120 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Notifications.swift @@ -0,0 +1,55 @@ +// +// Notifications.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +extension Notification.Name { + /// Used as a namespace for all `URLSessionTask` related notifications. + public struct Task { + /// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`. + public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume") + + /// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`. + public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend") + + /// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`. + public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel") + + /// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`. + public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete") + } +} + +// MARK: - + +extension Notification { + /// Used as a namespace for all `Notification` user info dictionary keys. + public struct Key { + /// User info dictionary key representing the `URLSessionTask` associated with the notification. + public static let Task = "org.alamofire.notification.key.task" + + /// User info dictionary key representing the responseData associated with the notification. + public static let ResponseData = "org.alamofire.notification.key.responseData" + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/ParameterEncoding.swift b/SynchronyFinancial/Pods/Alamofire/Source/ParameterEncoding.swift new file mode 100644 index 0000000..4a54f2d --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/ParameterEncoding.swift @@ -0,0 +1,483 @@ +// +// ParameterEncoding.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// HTTP method definitions. +/// +/// See https://tools.ietf.org/html/rfc7231#section-4.3 +public enum HTTPMethod: String { + case options = "OPTIONS" + case get = "GET" + case head = "HEAD" + case post = "POST" + case put = "PUT" + case patch = "PATCH" + case delete = "DELETE" + case trace = "TRACE" + case connect = "CONNECT" +} + +// MARK: - + +/// A dictionary of parameters to apply to a `URLRequest`. +public typealias Parameters = [String: Any] + +/// A type used to define how a set of parameters are applied to a `URLRequest`. +public protocol ParameterEncoding { + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `AFError.parameterEncodingFailed` error if encoding fails. + /// + /// - returns: The encoded request. + func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest +} + +// MARK: - + +/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP +/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as +/// the HTTP body depends on the destination of the encoding. +/// +/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to +/// `application/x-www-form-urlencoded; charset=utf-8`. +/// +/// There is no published specification for how to encode collection types. By default the convention of appending +/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for +/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the +/// square brackets appended to array keys. +/// +/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode +/// `true` as 1 and `false` as 0. +public struct URLEncoding: ParameterEncoding { + + // MARK: Helper Types + + /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the + /// resulting URL request. + /// + /// - methodDependent: Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` + /// requests and sets as the HTTP body for requests with any other HTTP method. + /// - queryString: Sets or appends encoded query string result to existing query string. + /// - httpBody: Sets encoded query string result as the HTTP body of the URL request. + public enum Destination { + case methodDependent, queryString, httpBody + } + + /// Configures how `Array` parameters are encoded. + /// + /// - brackets: An empty set of square brackets is appended to the key for every value. + /// This is the default behavior. + /// - noBrackets: No brackets are appended. The key is encoded as is. + public enum ArrayEncoding { + case brackets, noBrackets + + func encode(key: String) -> String { + switch self { + case .brackets: + return "\(key)[]" + case .noBrackets: + return key + } + } + } + + /// Configures how `Bool` parameters are encoded. + /// + /// - numeric: Encode `true` as `1` and `false` as `0`. This is the default behavior. + /// - literal: Encode `true` and `false` as string literals. + public enum BoolEncoding { + case numeric, literal + + func encode(value: Bool) -> String { + switch self { + case .numeric: + return value ? "1" : "0" + case .literal: + return value ? "true" : "false" + } + } + } + + // MARK: Properties + + /// Returns a default `URLEncoding` instance. + public static var `default`: URLEncoding { return URLEncoding() } + + /// Returns a `URLEncoding` instance with a `.methodDependent` destination. + public static var methodDependent: URLEncoding { return URLEncoding() } + + /// Returns a `URLEncoding` instance with a `.queryString` destination. + public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) } + + /// Returns a `URLEncoding` instance with an `.httpBody` destination. + public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) } + + /// The destination defining where the encoded query string is to be applied to the URL request. + public let destination: Destination + + /// The encoding to use for `Array` parameters. + public let arrayEncoding: ArrayEncoding + + /// The encoding to use for `Bool` parameters. + public let boolEncoding: BoolEncoding + + // MARK: Initialization + + /// Creates a `URLEncoding` instance using the specified destination. + /// + /// - parameter destination: The destination defining where the encoded query string is to be applied. + /// - parameter arrayEncoding: The encoding to use for `Array` parameters. + /// - parameter boolEncoding: The encoding to use for `Bool` parameters. + /// + /// - returns: The new `URLEncoding` instance. + public init(destination: Destination = .methodDependent, arrayEncoding: ArrayEncoding = .brackets, boolEncoding: BoolEncoding = .numeric) { + self.destination = destination + self.arrayEncoding = arrayEncoding + self.boolEncoding = boolEncoding + } + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let parameters = parameters else { return urlRequest } + + if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) { + guard let url = urlRequest.url else { + throw AFError.parameterEncodingFailed(reason: .missingURL) + } + + if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { + let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) + urlComponents.percentEncodedQuery = percentEncodedQuery + urlRequest.url = urlComponents.url + } + } else { + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false) + } + + return urlRequest + } + + /// Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion. + /// + /// - parameter key: The key of the query component. + /// - parameter value: The value of the query component. + /// + /// - returns: The percent-escaped, URL encoded query string components. + public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] { + var components: [(String, String)] = [] + + if let dictionary = value as? [String: Any] { + for (nestedKey, value) in dictionary { + components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value) + } + } else if let array = value as? [Any] { + for value in array { + components += queryComponents(fromKey: arrayEncoding.encode(key: key), value: value) + } + } else if let value = value as? NSNumber { + if value.isBool { + components.append((escape(key), escape(boolEncoding.encode(value: value.boolValue)))) + } else { + components.append((escape(key), escape("\(value)"))) + } + } else if let bool = value as? Bool { + components.append((escape(key), escape(boolEncoding.encode(value: bool)))) + } else { + components.append((escape(key), escape("\(value)"))) + } + + return components + } + + /// Returns a percent-escaped string following RFC 3986 for a query string key or value. + /// + /// RFC 3986 states that the following characters are "reserved" characters. + /// + /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/" + /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" + /// + /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow + /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" + /// should be percent-escaped in the query string. + /// + /// - parameter string: The string to be percent-escaped. + /// + /// - returns: The percent-escaped string. + public func escape(_ string: String) -> String { + let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 + let subDelimitersToEncode = "!$&'()*+,;=" + + var allowedCharacterSet = CharacterSet.urlQueryAllowed + allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)") + + var escaped = "" + + //========================================================================================================== + // + // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few + // hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no + // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more + // info, please refer to: + // + // - https://github.com/Alamofire/Alamofire/issues/206 + // + //========================================================================================================== + + if #available(iOS 8.3, *) { + escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string + } else { + let batchSize = 50 + var index = string.startIndex + + while index != string.endIndex { + let startIndex = index + let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex + let range = startIndex.. String { + var components: [(String, String)] = [] + + for key in parameters.keys.sorted(by: <) { + let value = parameters[key]! + components += queryComponents(fromKey: key, value: value) + } + return components.map { "\($0)=\($1)" }.joined(separator: "&") + } + + private func encodesParametersInURL(with method: HTTPMethod) -> Bool { + switch destination { + case .queryString: + return true + case .httpBody: + return false + default: + break + } + + switch method { + case .get, .head, .delete: + return true + default: + return false + } + } +} + +// MARK: - + +/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the +/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`. +public struct JSONEncoding: ParameterEncoding { + + // MARK: Properties + + /// Returns a `JSONEncoding` instance with default writing options. + public static var `default`: JSONEncoding { return JSONEncoding() } + + /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options. + public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) } + + /// The options for writing the parameters as JSON data. + public let options: JSONSerialization.WritingOptions + + // MARK: Initialization + + /// Creates a `JSONEncoding` instance using the specified options. + /// + /// - parameter options: The options for writing the parameters as JSON data. + /// + /// - returns: The new `JSONEncoding` instance. + public init(options: JSONSerialization.WritingOptions = []) { + self.options = options + } + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let parameters = parameters else { return urlRequest } + + do { + let data = try JSONSerialization.data(withJSONObject: parameters, options: options) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = data + } catch { + throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) + } + + return urlRequest + } + + /// Creates a URL request by encoding the JSON object and setting the resulting data on the HTTP body. + /// + /// - parameter urlRequest: The request to apply the JSON object to. + /// - parameter jsonObject: The JSON object to apply to the request. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let jsonObject = jsonObject else { return urlRequest } + + do { + let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = data + } catch { + throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) + } + + return urlRequest + } +} + +// MARK: - + +/// Uses `PropertyListSerialization` to create a plist representation of the parameters object, according to the +/// associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header +/// field of an encoded request is set to `application/x-plist`. +public struct PropertyListEncoding: ParameterEncoding { + + // MARK: Properties + + /// Returns a default `PropertyListEncoding` instance. + public static var `default`: PropertyListEncoding { return PropertyListEncoding() } + + /// Returns a `PropertyListEncoding` instance with xml formatting and default writing options. + public static var xml: PropertyListEncoding { return PropertyListEncoding(format: .xml) } + + /// Returns a `PropertyListEncoding` instance with binary formatting and default writing options. + public static var binary: PropertyListEncoding { return PropertyListEncoding(format: .binary) } + + /// The property list serialization format. + public let format: PropertyListSerialization.PropertyListFormat + + /// The options for writing the parameters as plist data. + public let options: PropertyListSerialization.WriteOptions + + // MARK: Initialization + + /// Creates a `PropertyListEncoding` instance using the specified format and options. + /// + /// - parameter format: The property list serialization format. + /// - parameter options: The options for writing the parameters as plist data. + /// + /// - returns: The new `PropertyListEncoding` instance. + public init( + format: PropertyListSerialization.PropertyListFormat = .xml, + options: PropertyListSerialization.WriteOptions = 0) + { + self.format = format + self.options = options + } + + // MARK: Encoding + + /// Creates a URL request by encoding parameters and applying them onto an existing request. + /// + /// - parameter urlRequest: The request to have parameters applied. + /// - parameter parameters: The parameters to apply. + /// + /// - throws: An `Error` if the encoding process encounters an error. + /// + /// - returns: The encoded request. + public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { + var urlRequest = try urlRequest.asURLRequest() + + guard let parameters = parameters else { return urlRequest } + + do { + let data = try PropertyListSerialization.data( + fromPropertyList: parameters, + format: format, + options: options + ) + + if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { + urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type") + } + + urlRequest.httpBody = data + } catch { + throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error)) + } + + return urlRequest + } +} + +// MARK: - + +extension NSNumber { + fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Request.swift b/SynchronyFinancial/Pods/Alamofire/Source/Request.swift new file mode 100644 index 0000000..ea43411 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Request.swift @@ -0,0 +1,654 @@ +// +// Request.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary. +public protocol RequestAdapter { + /// Inspects and adapts the specified `URLRequest` in some manner if necessary and returns the result. + /// + /// - parameter urlRequest: The URL request to adapt. + /// + /// - throws: An `Error` if the adaptation encounters an error. + /// + /// - returns: The adapted `URLRequest`. + func adapt(_ urlRequest: URLRequest) throws -> URLRequest +} + +// MARK: - + +/// A closure executed when the `RequestRetrier` determines whether a `Request` should be retried or not. +public typealias RequestRetryCompletion = (_ shouldRetry: Bool, _ timeDelay: TimeInterval) -> Void + +/// A type that determines whether a request should be retried after being executed by the specified session manager +/// and encountering an error. +public protocol RequestRetrier { + /// Determines whether the `Request` should be retried by calling the `completion` closure. + /// + /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs + /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly + /// cleaned up after. + /// + /// - parameter manager: The session manager the request was executed on. + /// - parameter request: The request that failed due to the encountered error. + /// - parameter error: The error encountered when executing the request. + /// - parameter completion: The completion closure to be executed when retry decision has been determined. + func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) +} + +// MARK: - + +protocol TaskConvertible { + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask +} + +/// A dictionary of headers to apply to a `URLRequest`. +public typealias HTTPHeaders = [String: String] + +// MARK: - + +/// Responsible for sending a request and receiving the response and associated data from the server, as well as +/// managing its underlying `URLSessionTask`. +open class Request { + + // MARK: Helper Types + + /// A closure executed when monitoring upload or download progress of a request. + public typealias ProgressHandler = (Progress) -> Void + + enum RequestTask { + case data(TaskConvertible?, URLSessionTask?) + case download(TaskConvertible?, URLSessionTask?) + case upload(TaskConvertible?, URLSessionTask?) + case stream(TaskConvertible?, URLSessionTask?) + } + + // MARK: Properties + + /// The delegate for the underlying task. + open internal(set) var delegate: TaskDelegate { + get { + taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() } + return taskDelegate + } + set { + taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() } + taskDelegate = newValue + } + } + + /// The underlying task. + open var task: URLSessionTask? { return delegate.task } + + /// The session belonging to the underlying task. + public let session: URLSession + + /// The request sent or to be sent to the server. + open var request: URLRequest? { return task?.originalRequest } + + /// The response received from the server, if any. + open var response: HTTPURLResponse? { return task?.response as? HTTPURLResponse } + + /// The number of times the request has been retried. + open internal(set) var retryCount: UInt = 0 + + let originalTask: TaskConvertible? + + var startTime: CFAbsoluteTime? + var endTime: CFAbsoluteTime? + + var validations: [() -> Void] = [] + + private var taskDelegate: TaskDelegate + private var taskDelegateLock = NSLock() + + // MARK: Lifecycle + + init(session: URLSession, requestTask: RequestTask, error: Error? = nil) { + self.session = session + + switch requestTask { + case .data(let originalTask, let task): + taskDelegate = DataTaskDelegate(task: task) + self.originalTask = originalTask + case .download(let originalTask, let task): + taskDelegate = DownloadTaskDelegate(task: task) + self.originalTask = originalTask + case .upload(let originalTask, let task): + taskDelegate = UploadTaskDelegate(task: task) + self.originalTask = originalTask + case .stream(let originalTask, let task): + taskDelegate = TaskDelegate(task: task) + self.originalTask = originalTask + } + + delegate.error = error + delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() } + } + + // MARK: Authentication + + /// Associates an HTTP Basic credential with the request. + /// + /// - parameter user: The user. + /// - parameter password: The password. + /// - parameter persistence: The URL credential persistence. `.ForSession` by default. + /// + /// - returns: The request. + @discardableResult + open func authenticate( + user: String, + password: String, + persistence: URLCredential.Persistence = .forSession) + -> Self + { + let credential = URLCredential(user: user, password: password, persistence: persistence) + return authenticate(usingCredential: credential) + } + + /// Associates a specified credential with the request. + /// + /// - parameter credential: The credential. + /// + /// - returns: The request. + @discardableResult + open func authenticate(usingCredential credential: URLCredential) -> Self { + delegate.credential = credential + return self + } + + /// Returns a base64 encoded basic authentication credential as an authorization header tuple. + /// + /// - parameter user: The user. + /// - parameter password: The password. + /// + /// - returns: A tuple with Authorization header and credential value if encoding succeeds, `nil` otherwise. + open class func authorizationHeader(user: String, password: String) -> (key: String, value: String)? { + guard let data = "\(user):\(password)".data(using: .utf8) else { return nil } + + let credential = data.base64EncodedString(options: []) + + return (key: "Authorization", value: "Basic \(credential)") + } + + // MARK: State + + /// Resumes the request. + open func resume() { + guard let task = task else { delegate.queue.isSuspended = false ; return } + + if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() } + + task.resume() + + NotificationCenter.default.post( + name: Notification.Name.Task.DidResume, + object: self, + userInfo: [Notification.Key.Task: task] + ) + } + + /// Suspends the request. + open func suspend() { + guard let task = task else { return } + + task.suspend() + + NotificationCenter.default.post( + name: Notification.Name.Task.DidSuspend, + object: self, + userInfo: [Notification.Key.Task: task] + ) + } + + /// Cancels the request. + open func cancel() { + guard let task = task else { return } + + task.cancel() + + NotificationCenter.default.post( + name: Notification.Name.Task.DidCancel, + object: self, + userInfo: [Notification.Key.Task: task] + ) + } +} + +// MARK: - CustomStringConvertible + +extension Request: CustomStringConvertible { + /// The textual representation used when written to an output stream, which includes the HTTP method and URL, as + /// well as the response status code if a response has been received. + open var description: String { + var components: [String] = [] + + if let HTTPMethod = request?.httpMethod { + components.append(HTTPMethod) + } + + if let urlString = request?.url?.absoluteString { + components.append(urlString) + } + + if let response = response { + components.append("(\(response.statusCode))") + } + + return components.joined(separator: " ") + } +} + +// MARK: - CustomDebugStringConvertible + +extension Request: CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, in the form of a cURL command. + open var debugDescription: String { + return cURLRepresentation() + } + + func cURLRepresentation() -> String { + var components = ["$ curl -v"] + + guard let request = self.request, + let url = request.url, + let host = url.host + else { + return "$ curl command could not be created" + } + + if let httpMethod = request.httpMethod, httpMethod != "GET" { + components.append("-X \(httpMethod)") + } + + if let credentialStorage = self.session.configuration.urlCredentialStorage { + let protectionSpace = URLProtectionSpace( + host: host, + port: url.port ?? 0, + protocol: url.scheme, + realm: host, + authenticationMethod: NSURLAuthenticationMethodHTTPBasic + ) + + if let credentials = credentialStorage.credentials(for: protectionSpace)?.values { + for credential in credentials { + guard let user = credential.user, let password = credential.password else { continue } + components.append("-u \(user):\(password)") + } + } else { + if let credential = delegate.credential, let user = credential.user, let password = credential.password { + components.append("-u \(user):\(password)") + } + } + } + + if session.configuration.httpShouldSetCookies { + if + let cookieStorage = session.configuration.httpCookieStorage, + let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty + { + let string = cookies.reduce("") { $0 + "\($1.name)=\($1.value);" } + + #if swift(>=3.2) + components.append("-b \"\(string[.. URLSessionTask { + do { + let urlRequest = try self.urlRequest.adapt(using: adapter) + return queue.sync { session.dataTask(with: urlRequest) } + } catch { + throw AdaptError(error: error) + } + } + } + + // MARK: Properties + + /// The request sent or to be sent to the server. + open override var request: URLRequest? { + if let request = super.request { return request } + if let requestable = originalTask as? Requestable { return requestable.urlRequest } + + return nil + } + + /// The progress of fetching the response data from the server for the request. + open var progress: Progress { return dataDelegate.progress } + + var dataDelegate: DataTaskDelegate { return delegate as! DataTaskDelegate } + + // MARK: Stream + + /// Sets a closure to be called periodically during the lifecycle of the request as data is read from the server. + /// + /// This closure returns the bytes most recently received from the server, not including data from previous calls. + /// If this closure is set, data will only be available within this closure, and will not be saved elsewhere. It is + /// also important to note that the server data in any `Response` object will be `nil`. + /// + /// - parameter closure: The code to be executed periodically during the lifecycle of the request. + /// + /// - returns: The request. + @discardableResult + open func stream(closure: ((Data) -> Void)? = nil) -> Self { + dataDelegate.dataStream = closure + return self + } + + // MARK: Progress + + /// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server. + /// + /// - parameter queue: The dispatch queue to execute the closure on. + /// - parameter closure: The code to be executed periodically as data is read from the server. + /// + /// - returns: The request. + @discardableResult + open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self { + dataDelegate.progressHandler = (closure, queue) + return self + } +} + +// MARK: - + +/// Specific type of `Request` that manages an underlying `URLSessionDownloadTask`. +open class DownloadRequest: Request { + + // MARK: Helper Types + + /// A collection of options to be executed prior to moving a downloaded file from the temporary URL to the + /// destination URL. + public struct DownloadOptions: OptionSet { + /// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol. + public let rawValue: UInt + + /// A `DownloadOptions` flag that creates intermediate directories for the destination URL if specified. + public static let createIntermediateDirectories = DownloadOptions(rawValue: 1 << 0) + + /// A `DownloadOptions` flag that removes a previous file from the destination URL if specified. + public static let removePreviousFile = DownloadOptions(rawValue: 1 << 1) + + /// Creates a `DownloadFileDestinationOptions` instance with the specified raw value. + /// + /// - parameter rawValue: The raw bitmask value for the option. + /// + /// - returns: A new log level instance. + public init(rawValue: UInt) { + self.rawValue = rawValue + } + } + + /// A closure executed once a download request has successfully completed in order to determine where to move the + /// temporary file written to during the download process. The closure takes two arguments: the temporary file URL + /// and the URL response, and returns a two arguments: the file URL where the temporary file should be moved and + /// the options defining how the file should be moved. + public typealias DownloadFileDestination = ( + _ temporaryURL: URL, + _ response: HTTPURLResponse) + -> (destinationURL: URL, options: DownloadOptions) + + enum Downloadable: TaskConvertible { + case request(URLRequest) + case resumeData(Data) + + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask { + do { + let task: URLSessionTask + + switch self { + case let .request(urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.downloadTask(with: urlRequest) } + case let .resumeData(resumeData): + task = queue.sync { session.downloadTask(withResumeData: resumeData) } + } + + return task + } catch { + throw AdaptError(error: error) + } + } + } + + // MARK: Properties + + /// The request sent or to be sent to the server. + open override var request: URLRequest? { + if let request = super.request { return request } + + if let downloadable = originalTask as? Downloadable, case let .request(urlRequest) = downloadable { + return urlRequest + } + + return nil + } + + /// The resume data of the underlying download task if available after a failure. + open var resumeData: Data? { return downloadDelegate.resumeData } + + /// The progress of downloading the response data from the server for the request. + open var progress: Progress { return downloadDelegate.progress } + + var downloadDelegate: DownloadTaskDelegate { return delegate as! DownloadTaskDelegate } + + // MARK: State + + /// Cancels the request. + open override func cancel() { + downloadDelegate.downloadTask.cancel { self.downloadDelegate.resumeData = $0 } + + NotificationCenter.default.post( + name: Notification.Name.Task.DidCancel, + object: self, + userInfo: [Notification.Key.Task: task as Any] + ) + } + + // MARK: Progress + + /// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server. + /// + /// - parameter queue: The dispatch queue to execute the closure on. + /// - parameter closure: The code to be executed periodically as data is read from the server. + /// + /// - returns: The request. + @discardableResult + open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self { + downloadDelegate.progressHandler = (closure, queue) + return self + } + + // MARK: Destination + + /// Creates a download file destination closure which uses the default file manager to move the temporary file to a + /// file URL in the first available directory with the specified search path directory and search path domain mask. + /// + /// - parameter directory: The search path directory. `.DocumentDirectory` by default. + /// - parameter domain: The search path domain mask. `.UserDomainMask` by default. + /// + /// - returns: A download file destination closure. + open class func suggestedDownloadDestination( + for directory: FileManager.SearchPathDirectory = .documentDirectory, + in domain: FileManager.SearchPathDomainMask = .userDomainMask) + -> DownloadFileDestination + { + return { temporaryURL, response in + let directoryURLs = FileManager.default.urls(for: directory, in: domain) + + if !directoryURLs.isEmpty { + return (directoryURLs[0].appendingPathComponent(response.suggestedFilename!), []) + } + + return (temporaryURL, []) + } + } +} + +// MARK: - + +/// Specific type of `Request` that manages an underlying `URLSessionUploadTask`. +open class UploadRequest: DataRequest { + + // MARK: Helper Types + + enum Uploadable: TaskConvertible { + case data(Data, URLRequest) + case file(URL, URLRequest) + case stream(InputStream, URLRequest) + + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask { + do { + let task: URLSessionTask + + switch self { + case let .data(data, urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.uploadTask(with: urlRequest, from: data) } + case let .file(url, urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.uploadTask(with: urlRequest, fromFile: url) } + case let .stream(_, urlRequest): + let urlRequest = try urlRequest.adapt(using: adapter) + task = queue.sync { session.uploadTask(withStreamedRequest: urlRequest) } + } + + return task + } catch { + throw AdaptError(error: error) + } + } + } + + // MARK: Properties + + /// The request sent or to be sent to the server. + open override var request: URLRequest? { + if let request = super.request { return request } + + guard let uploadable = originalTask as? Uploadable else { return nil } + + switch uploadable { + case .data(_, let urlRequest), .file(_, let urlRequest), .stream(_, let urlRequest): + return urlRequest + } + } + + /// The progress of uploading the payload to the server for the upload request. + open var uploadProgress: Progress { return uploadDelegate.uploadProgress } + + var uploadDelegate: UploadTaskDelegate { return delegate as! UploadTaskDelegate } + + // MARK: Upload Progress + + /// Sets a closure to be called periodically during the lifecycle of the `UploadRequest` as data is sent to + /// the server. + /// + /// After the data is sent to the server, the `progress(queue:closure:)` APIs can be used to monitor the progress + /// of data being read from the server. + /// + /// - parameter queue: The dispatch queue to execute the closure on. + /// - parameter closure: The code to be executed periodically as data is sent to the server. + /// + /// - returns: The request. + @discardableResult + open func uploadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self { + uploadDelegate.uploadProgressHandler = (closure, queue) + return self + } +} + +// MARK: - + +#if !os(watchOS) + +/// Specific type of `Request` that manages an underlying `URLSessionStreamTask`. +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +open class StreamRequest: Request { + enum Streamable: TaskConvertible { + case stream(hostName: String, port: Int) + case netService(NetService) + + func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask { + let task: URLSessionTask + + switch self { + case let .stream(hostName, port): + task = queue.sync { session.streamTask(withHostName: hostName, port: port) } + case let .netService(netService): + task = queue.sync { session.streamTask(with: netService) } + } + + return task + } + } +} + +#endif diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Response.swift b/SynchronyFinancial/Pods/Alamofire/Source/Response.swift new file mode 100644 index 0000000..74b1ef5 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Response.swift @@ -0,0 +1,567 @@ +// +// Response.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Used to store all data associated with an non-serialized response of a data or upload request. +public struct DefaultDataResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The data returned by the server. + public let data: Data? + + /// The error encountered while executing or validating the request. + public let error: Error? + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + var _metrics: AnyObject? + + /// Creates a `DefaultDataResponse` instance from the specified parameters. + /// + /// - Parameters: + /// - request: The URL request sent to the server. + /// - response: The server's response to the URL request. + /// - data: The data returned by the server. + /// - error: The error encountered while executing or validating the request. + /// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default. + /// - metrics: The task metrics containing the request / response statistics. `nil` by default. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + data: Data?, + error: Error?, + timeline: Timeline = Timeline(), + metrics: AnyObject? = nil) + { + self.request = request + self.response = response + self.data = data + self.error = error + self.timeline = timeline + } +} + +// MARK: - + +/// Used to store all data associated with a serialized response of a data or upload request. +public struct DataResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The data returned by the server. + public let data: Data? + + /// The result of response serialization. + public let result: Result + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + /// Returns the associated value of the result if it is a success, `nil` otherwise. + public var value: Value? { return result.value } + + /// Returns the associated error value if the result if it is a failure, `nil` otherwise. + public var error: Error? { return result.error } + + var _metrics: AnyObject? + + /// Creates a `DataResponse` instance with the specified parameters derived from response serialization. + /// + /// - parameter request: The URL request sent to the server. + /// - parameter response: The server's response to the URL request. + /// - parameter data: The data returned by the server. + /// - parameter result: The result of response serialization. + /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. + /// + /// - returns: The new `DataResponse` instance. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + data: Data?, + result: Result, + timeline: Timeline = Timeline()) + { + self.request = request + self.response = response + self.data = data + self.result = result + self.timeline = timeline + } +} + +// MARK: - + +extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, which includes whether the result was a + /// success or failure. + public var description: String { + return result.debugDescription + } + + /// The debug textual representation used when written to an output stream, which includes the URL request, the URL + /// response, the server data, the response serialization result and the timeline. + public var debugDescription: String { + var output: [String] = [] + + output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil") + output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") + output.append("[Data]: \(data?.count ?? 0) bytes") + output.append("[Result]: \(result.debugDescription)") + output.append("[Timeline]: \(timeline.debugDescription)") + + return output.joined(separator: "\n") + } +} + +// MARK: - + +extension DataResponse { + /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped + /// result value as a parameter. + /// + /// Use the `map` method with a closure that does not throw. For example: + /// + /// let possibleData: DataResponse = ... + /// let possibleInt = possibleData.map { $0.count } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's + /// result is a failure, returns a response wrapping the same failure. + public func map(_ transform: (Value) -> T) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.map(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result + /// value as a parameter. + /// + /// Use the `flatMap` method with a closure that may throw an error. For example: + /// + /// let possibleData: DataResponse = ... + /// let possibleObject = possibleData.flatMap { + /// try JSONSerialization.jsonObject(with: $0) + /// } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's + /// result is a failure, returns the same failure. + public func flatMap(_ transform: (Value) throws -> T) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.flatMap(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `mapError` function with a closure that does not throw. For example: + /// + /// let possibleData: DataResponse = ... + /// let withMyError = possibleData.mapError { MyError.error($0) } + /// + /// - Parameter transform: A closure that takes the error of the instance. + /// - Returns: A `DataResponse` instance containing the result of the transform. + public func mapError(_ transform: (Error) -> E) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.mapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `flatMapError` function with a closure that may throw an error. For example: + /// + /// let possibleData: DataResponse = ... + /// let possibleObject = possibleData.flatMapError { + /// try someFailableFunction(taking: $0) + /// } + /// + /// - Parameter transform: A throwing closure that takes the error of the instance. + /// + /// - Returns: A `DataResponse` instance containing the result of the transform. + public func flatMapError(_ transform: (Error) throws -> E) -> DataResponse { + var response = DataResponse( + request: request, + response: self.response, + data: data, + result: result.flatMapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } +} + +// MARK: - + +/// Used to store all data associated with an non-serialized response of a download request. +public struct DefaultDownloadResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The temporary destination URL of the data returned from the server. + public let temporaryURL: URL? + + /// The final destination URL of the data returned from the server if it was moved. + public let destinationURL: URL? + + /// The resume data generated if the request was cancelled. + public let resumeData: Data? + + /// The error encountered while executing or validating the request. + public let error: Error? + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + var _metrics: AnyObject? + + /// Creates a `DefaultDownloadResponse` instance from the specified parameters. + /// + /// - Parameters: + /// - request: The URL request sent to the server. + /// - response: The server's response to the URL request. + /// - temporaryURL: The temporary destination URL of the data returned from the server. + /// - destinationURL: The final destination URL of the data returned from the server if it was moved. + /// - resumeData: The resume data generated if the request was cancelled. + /// - error: The error encountered while executing or validating the request. + /// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default. + /// - metrics: The task metrics containing the request / response statistics. `nil` by default. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + temporaryURL: URL?, + destinationURL: URL?, + resumeData: Data?, + error: Error?, + timeline: Timeline = Timeline(), + metrics: AnyObject? = nil) + { + self.request = request + self.response = response + self.temporaryURL = temporaryURL + self.destinationURL = destinationURL + self.resumeData = resumeData + self.error = error + self.timeline = timeline + } +} + +// MARK: - + +/// Used to store all data associated with a serialized response of a download request. +public struct DownloadResponse { + /// The URL request sent to the server. + public let request: URLRequest? + + /// The server's response to the URL request. + public let response: HTTPURLResponse? + + /// The temporary destination URL of the data returned from the server. + public let temporaryURL: URL? + + /// The final destination URL of the data returned from the server if it was moved. + public let destinationURL: URL? + + /// The resume data generated if the request was cancelled. + public let resumeData: Data? + + /// The result of response serialization. + public let result: Result + + /// The timeline of the complete lifecycle of the request. + public let timeline: Timeline + + /// Returns the associated value of the result if it is a success, `nil` otherwise. + public var value: Value? { return result.value } + + /// Returns the associated error value if the result if it is a failure, `nil` otherwise. + public var error: Error? { return result.error } + + var _metrics: AnyObject? + + /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization. + /// + /// - parameter request: The URL request sent to the server. + /// - parameter response: The server's response to the URL request. + /// - parameter temporaryURL: The temporary destination URL of the data returned from the server. + /// - parameter destinationURL: The final destination URL of the data returned from the server if it was moved. + /// - parameter resumeData: The resume data generated if the request was cancelled. + /// - parameter result: The result of response serialization. + /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. + /// + /// - returns: The new `DownloadResponse` instance. + public init( + request: URLRequest?, + response: HTTPURLResponse?, + temporaryURL: URL?, + destinationURL: URL?, + resumeData: Data?, + result: Result, + timeline: Timeline = Timeline()) + { + self.request = request + self.response = response + self.temporaryURL = temporaryURL + self.destinationURL = destinationURL + self.resumeData = resumeData + self.result = result + self.timeline = timeline + } +} + +// MARK: - + +extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, which includes whether the result was a + /// success or failure. + public var description: String { + return result.debugDescription + } + + /// The debug textual representation used when written to an output stream, which includes the URL request, the URL + /// response, the temporary and destination URLs, the resume data, the response serialization result and the + /// timeline. + public var debugDescription: String { + var output: [String] = [] + + output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil") + output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") + output.append("[TemporaryURL]: \(temporaryURL?.path ?? "nil")") + output.append("[DestinationURL]: \(destinationURL?.path ?? "nil")") + output.append("[ResumeData]: \(resumeData?.count ?? 0) bytes") + output.append("[Result]: \(result.debugDescription)") + output.append("[Timeline]: \(timeline.debugDescription)") + + return output.joined(separator: "\n") + } +} + +// MARK: - + +extension DownloadResponse { + /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped + /// result value as a parameter. + /// + /// Use the `map` method with a closure that does not throw. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let possibleInt = possibleData.map { $0.count } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's + /// result is a failure, returns a response wrapping the same failure. + public func map(_ transform: (Value) -> T) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.map(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped + /// result value as a parameter. + /// + /// Use the `flatMap` method with a closure that may throw an error. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let possibleObject = possibleData.flatMap { + /// try JSONSerialization.jsonObject(with: $0) + /// } + /// + /// - parameter transform: A closure that takes the success value of the instance's result. + /// + /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this + /// instance's result is a failure, returns the same failure. + public func flatMap(_ transform: (Value) throws -> T) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.flatMap(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `mapError` function with a closure that does not throw. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let withMyError = possibleData.mapError { MyError.error($0) } + /// + /// - Parameter transform: A closure that takes the error of the instance. + /// - Returns: A `DownloadResponse` instance containing the result of the transform. + public func mapError(_ transform: (Error) -> E) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.mapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } + + /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `flatMapError` function with a closure that may throw an error. For example: + /// + /// let possibleData: DownloadResponse = ... + /// let possibleObject = possibleData.flatMapError { + /// try someFailableFunction(taking: $0) + /// } + /// + /// - Parameter transform: A throwing closure that takes the error of the instance. + /// + /// - Returns: A `DownloadResponse` instance containing the result of the transform. + public func flatMapError(_ transform: (Error) throws -> E) -> DownloadResponse { + var response = DownloadResponse( + request: request, + response: self.response, + temporaryURL: temporaryURL, + destinationURL: destinationURL, + resumeData: resumeData, + result: result.flatMapError(transform), + timeline: timeline + ) + + response._metrics = _metrics + + return response + } +} + +// MARK: - + +protocol Response { + /// The task metrics containing the request / response statistics. + var _metrics: AnyObject? { get set } + mutating func add(_ metrics: AnyObject?) +} + +extension Response { + mutating func add(_ metrics: AnyObject?) { + #if !os(watchOS) + guard #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) else { return } + guard let metrics = metrics as? URLSessionTaskMetrics else { return } + + _metrics = metrics + #endif + } +} + +// MARK: - + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DefaultDataResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DataResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DefaultDownloadResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} + +@available(iOS 10.0, macOS 10.12, tvOS 10.0, *) +extension DownloadResponse: Response { +#if !os(watchOS) + /// The task metrics containing the request / response statistics. + public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } +#endif +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/ResponseSerialization.swift b/SynchronyFinancial/Pods/Alamofire/Source/ResponseSerialization.swift new file mode 100644 index 0000000..3333726 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/ResponseSerialization.swift @@ -0,0 +1,715 @@ +// +// ResponseSerialization.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// The type in which all data response serializers must conform to in order to serialize a response. +public protocol DataResponseSerializerProtocol { + /// The type of serialized object to be created by this `DataResponseSerializerType`. + associatedtype SerializedObject + + /// A closure used by response handlers that takes a request, response, data and error and returns a result. + var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result { get } +} + +// MARK: - + +/// A generic `DataResponseSerializerType` used to serialize a request, response, and data into a serialized object. +public struct DataResponseSerializer: DataResponseSerializerProtocol { + /// The type of serialized object to be created by this `DataResponseSerializer`. + public typealias SerializedObject = Value + + /// A closure used by response handlers that takes a request, response, data and error and returns a result. + public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result + + /// Initializes the `ResponseSerializer` instance with the given serialize response closure. + /// + /// - parameter serializeResponse: The closure used to serialize the response. + /// + /// - returns: The new generic response serializer instance. + public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result) { + self.serializeResponse = serializeResponse + } +} + +// MARK: - + +/// The type in which all download response serializers must conform to in order to serialize a response. +public protocol DownloadResponseSerializerProtocol { + /// The type of serialized object to be created by this `DownloadResponseSerializerType`. + associatedtype SerializedObject + + /// A closure used by response handlers that takes a request, response, url and error and returns a result. + var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result { get } +} + +// MARK: - + +/// A generic `DownloadResponseSerializerType` used to serialize a request, response, and data into a serialized object. +public struct DownloadResponseSerializer: DownloadResponseSerializerProtocol { + /// The type of serialized object to be created by this `DownloadResponseSerializer`. + public typealias SerializedObject = Value + + /// A closure used by response handlers that takes a request, response, url and error and returns a result. + public var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result + + /// Initializes the `ResponseSerializer` instance with the given serialize response closure. + /// + /// - parameter serializeResponse: The closure used to serialize the response. + /// + /// - returns: The new generic response serializer instance. + public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result) { + self.serializeResponse = serializeResponse + } +} + +// MARK: - Timeline + +extension Request { + var timeline: Timeline { + let requestStartTime = self.startTime ?? CFAbsoluteTimeGetCurrent() + let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent() + let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime + + return Timeline( + requestStartTime: requestStartTime, + initialResponseTime: initialResponseTime, + requestCompletedTime: requestCompletedTime, + serializationCompletedTime: CFAbsoluteTimeGetCurrent() + ) + } +} + +// MARK: - Default + +extension DataRequest { + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self { + delegate.queue.addOperation { + (queue ?? DispatchQueue.main).async { + var dataResponse = DefaultDataResponse( + request: self.request, + response: self.response, + data: self.delegate.data, + error: self.delegate.error, + timeline: self.timeline + ) + + dataResponse.add(self.delegate.metrics) + + completionHandler(dataResponse) + } + } + + return self + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter responseSerializer: The response serializer responsible for serializing the request, response, + /// and data. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response( + queue: DispatchQueue? = nil, + responseSerializer: T, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + delegate.queue.addOperation { + let result = responseSerializer.serializeResponse( + self.request, + self.response, + self.delegate.data, + self.delegate.error + ) + + var dataResponse = DataResponse( + request: self.request, + response: self.response, + data: self.delegate.data, + result: result, + timeline: self.timeline + ) + + dataResponse.add(self.delegate.metrics) + + (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) } + } + + return self + } +} + +extension DownloadRequest { + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response( + queue: DispatchQueue? = nil, + completionHandler: @escaping (DefaultDownloadResponse) -> Void) + -> Self + { + delegate.queue.addOperation { + (queue ?? DispatchQueue.main).async { + var downloadResponse = DefaultDownloadResponse( + request: self.request, + response: self.response, + temporaryURL: self.downloadDelegate.temporaryURL, + destinationURL: self.downloadDelegate.destinationURL, + resumeData: self.downloadDelegate.resumeData, + error: self.downloadDelegate.error, + timeline: self.timeline + ) + + downloadResponse.add(self.delegate.metrics) + + completionHandler(downloadResponse) + } + } + + return self + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter queue: The queue on which the completion handler is dispatched. + /// - parameter responseSerializer: The response serializer responsible for serializing the request, response, + /// and data contained in the destination url. + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func response( + queue: DispatchQueue? = nil, + responseSerializer: T, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + delegate.queue.addOperation { + let result = responseSerializer.serializeResponse( + self.request, + self.response, + self.downloadDelegate.fileURL, + self.downloadDelegate.error + ) + + var downloadResponse = DownloadResponse( + request: self.request, + response: self.response, + temporaryURL: self.downloadDelegate.temporaryURL, + destinationURL: self.downloadDelegate.destinationURL, + resumeData: self.downloadDelegate.resumeData, + result: result, + timeline: self.timeline + ) + + downloadResponse.add(self.delegate.metrics) + + (queue ?? DispatchQueue.main).async { completionHandler(downloadResponse) } + } + + return self + } +} + +// MARK: - Data + +extension Request { + /// Returns a result data type that contains the response data as-is. + /// + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponseData(response: HTTPURLResponse?, data: Data?, error: Error?) -> Result { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(Data()) } + + guard let validData = data else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) + } + + return .success(validData) + } +} + +extension DataRequest { + /// Creates a response serializer that returns the associated data as-is. + /// + /// - returns: A data response serializer. + public static func dataResponseSerializer() -> DataResponseSerializer { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponseData(response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseData( + queue: DispatchQueue? = nil, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.dataResponseSerializer(), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns the associated data as-is. + /// + /// - returns: A data response serializer. + public static func dataResponseSerializer() -> DownloadResponseSerializer { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponseData(response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter completionHandler: The code to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseData( + queue: DispatchQueue? = nil, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.dataResponseSerializer(), + completionHandler: completionHandler + ) + } +} + +// MARK: - String + +extension Request { + /// Returns a result string type initialized from the response data with the specified string encoding. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server + /// response, falling back to the default HTTP default character set, ISO-8859-1. + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponseString( + encoding: String.Encoding?, + response: HTTPURLResponse?, + data: Data?, + error: Error?) + -> Result + { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success("") } + + guard let validData = data else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) + } + + var convertedEncoding = encoding + + if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil { + convertedEncoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding( + CFStringConvertIANACharSetNameToEncoding(encodingName)) + ) + } + + let actualEncoding = convertedEncoding ?? .isoLatin1 + + if let string = String(data: validData, encoding: actualEncoding) { + return .success(string) + } else { + return .failure(AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding))) + } + } +} + +extension DataRequest { + /// Creates a response serializer that returns a result string type initialized from the response data with + /// the specified string encoding. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server + /// response, falling back to the default HTTP default character set, ISO-8859-1. + /// + /// - returns: A string response serializer. + public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DataResponseSerializer { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the + /// server response, falling back to the default HTTP default character set, + /// ISO-8859-1. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseString( + queue: DispatchQueue? = nil, + encoding: String.Encoding? = nil, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns a result string type initialized from the response data with + /// the specified string encoding. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server + /// response, falling back to the default HTTP default character set, ISO-8859-1. + /// + /// - returns: A string response serializer. + public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DownloadResponseSerializer { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the + /// server response, falling back to the default HTTP default character set, + /// ISO-8859-1. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseString( + queue: DispatchQueue? = nil, + encoding: String.Encoding? = nil, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.stringResponseSerializer(encoding: encoding), + completionHandler: completionHandler + ) + } +} + +// MARK: - JSON + +extension Request { + /// Returns a JSON object contained in a result type constructed from the response data using `JSONSerialization` + /// with the specified reading options. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponseJSON( + options: JSONSerialization.ReadingOptions, + response: HTTPURLResponse?, + data: Data?, + error: Error?) + -> Result + { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) } + + guard let validData = data, validData.count > 0 else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)) + } + + do { + let json = try JSONSerialization.jsonObject(with: validData, options: options) + return .success(json) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error))) + } + } +} + +extension DataRequest { + /// Creates a response serializer that returns a JSON object result type constructed from the response data using + /// `JSONSerialization` with the specified reading options. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// + /// - returns: A JSON object response serializer. + public static func jsonResponseSerializer( + options: JSONSerialization.ReadingOptions = .allowFragments) + -> DataResponseSerializer + { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponseJSON(options: options, response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseJSON( + queue: DispatchQueue? = nil, + options: JSONSerialization.ReadingOptions = .allowFragments, + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.jsonResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns a JSON object result type constructed from the response data using + /// `JSONSerialization` with the specified reading options. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// + /// - returns: A JSON object response serializer. + public static func jsonResponseSerializer( + options: JSONSerialization.ReadingOptions = .allowFragments) + -> DownloadResponseSerializer + { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponseJSON(options: options, response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responseJSON( + queue: DispatchQueue? = nil, + options: JSONSerialization.ReadingOptions = .allowFragments, + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.jsonResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +// MARK: - Property List + +extension Request { + /// Returns a plist object contained in a result type constructed from the response data using + /// `PropertyListSerialization` with the specified reading options. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// - parameter response: The response from the server. + /// - parameter data: The data returned from the server. + /// - parameter error: The error already encountered if it exists. + /// + /// - returns: The result data type. + public static func serializeResponsePropertyList( + options: PropertyListSerialization.ReadOptions, + response: HTTPURLResponse?, + data: Data?, + error: Error?) + -> Result + { + guard error == nil else { return .failure(error!) } + + if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) } + + guard let validData = data, validData.count > 0 else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)) + } + + do { + let plist = try PropertyListSerialization.propertyList(from: validData, options: options, format: nil) + return .success(plist) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .propertyListSerializationFailed(error: error))) + } + } +} + +extension DataRequest { + /// Creates a response serializer that returns an object constructed from the response data using + /// `PropertyListSerialization` with the specified reading options. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// + /// - returns: A property list object response serializer. + public static func propertyListResponseSerializer( + options: PropertyListSerialization.ReadOptions = []) + -> DataResponseSerializer + { + return DataResponseSerializer { _, response, data, error in + return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error) + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responsePropertyList( + queue: DispatchQueue? = nil, + options: PropertyListSerialization.ReadOptions = [], + completionHandler: @escaping (DataResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DataRequest.propertyListResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +extension DownloadRequest { + /// Creates a response serializer that returns an object constructed from the response data using + /// `PropertyListSerialization` with the specified reading options. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// + /// - returns: A property list object response serializer. + public static func propertyListResponseSerializer( + options: PropertyListSerialization.ReadOptions = []) + -> DownloadResponseSerializer + { + return DownloadResponseSerializer { _, response, fileURL, error in + guard error == nil else { return .failure(error!) } + + guard let fileURL = fileURL else { + return .failure(AFError.responseSerializationFailed(reason: .inputFileNil)) + } + + do { + let data = try Data(contentsOf: fileURL) + return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error) + } catch { + return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL))) + } + } + } + + /// Adds a handler to be called once the request has finished. + /// + /// - parameter options: The property list reading options. Defaults to `[]`. + /// - parameter completionHandler: A closure to be executed once the request has finished. + /// + /// - returns: The request. + @discardableResult + public func responsePropertyList( + queue: DispatchQueue? = nil, + options: PropertyListSerialization.ReadOptions = [], + completionHandler: @escaping (DownloadResponse) -> Void) + -> Self + { + return response( + queue: queue, + responseSerializer: DownloadRequest.propertyListResponseSerializer(options: options), + completionHandler: completionHandler + ) + } +} + +/// A set of HTTP response status code that do not contain response data. +private let emptyDataStatusCodes: Set = [204, 205] diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Result.swift b/SynchronyFinancial/Pods/Alamofire/Source/Result.swift new file mode 100644 index 0000000..df62e12 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Result.swift @@ -0,0 +1,300 @@ +// +// Result.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Used to represent whether a request was successful or encountered an error. +/// +/// - success: The request and all post processing operations were successful resulting in the serialization of the +/// provided associated value. +/// +/// - failure: The request encountered an error resulting in a failure. The associated values are the original data +/// provided by the server as well as the error that caused the failure. +public enum Result { + case success(Value) + case failure(Error) + + /// Returns `true` if the result is a success, `false` otherwise. + public var isSuccess: Bool { + switch self { + case .success: + return true + case .failure: + return false + } + } + + /// Returns `true` if the result is a failure, `false` otherwise. + public var isFailure: Bool { + return !isSuccess + } + + /// Returns the associated value if the result is a success, `nil` otherwise. + public var value: Value? { + switch self { + case .success(let value): + return value + case .failure: + return nil + } + } + + /// Returns the associated error value if the result is a failure, `nil` otherwise. + public var error: Error? { + switch self { + case .success: + return nil + case .failure(let error): + return error + } + } +} + +// MARK: - CustomStringConvertible + +extension Result: CustomStringConvertible { + /// The textual representation used when written to an output stream, which includes whether the result was a + /// success or failure. + public var description: String { + switch self { + case .success: + return "SUCCESS" + case .failure: + return "FAILURE" + } + } +} + +// MARK: - CustomDebugStringConvertible + +extension Result: CustomDebugStringConvertible { + /// The debug textual representation used when written to an output stream, which includes whether the result was a + /// success or failure in addition to the value or error. + public var debugDescription: String { + switch self { + case .success(let value): + return "SUCCESS: \(value)" + case .failure(let error): + return "FAILURE: \(error)" + } + } +} + +// MARK: - Functional APIs + +extension Result { + /// Creates a `Result` instance from the result of a closure. + /// + /// A failure result is created when the closure throws, and a success result is created when the closure + /// succeeds without throwing an error. + /// + /// func someString() throws -> String { ... } + /// + /// let result = Result(value: { + /// return try someString() + /// }) + /// + /// // The type of result is Result + /// + /// The trailing closure syntax is also supported: + /// + /// let result = Result { try someString() } + /// + /// - parameter value: The closure to execute and create the result for. + public init(value: () throws -> Value) { + do { + self = try .success(value()) + } catch { + self = .failure(error) + } + } + + /// Returns the success value, or throws the failure error. + /// + /// let possibleString: Result = .success("success") + /// try print(possibleString.unwrap()) + /// // Prints "success" + /// + /// let noString: Result = .failure(error) + /// try print(noString.unwrap()) + /// // Throws error + public func unwrap() throws -> Value { + switch self { + case .success(let value): + return value + case .failure(let error): + throw error + } + } + + /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. + /// + /// Use the `map` method with a closure that does not throw. For example: + /// + /// let possibleData: Result = .success(Data()) + /// let possibleInt = possibleData.map { $0.count } + /// try print(possibleInt.unwrap()) + /// // Prints "0" + /// + /// let noData: Result = .failure(error) + /// let noInt = noData.map { $0.count } + /// try print(noInt.unwrap()) + /// // Throws error + /// + /// - parameter transform: A closure that takes the success value of the `Result` instance. + /// + /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the + /// same failure. + public func map(_ transform: (Value) -> T) -> Result { + switch self { + case .success(let value): + return .success(transform(value)) + case .failure(let error): + return .failure(error) + } + } + + /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. + /// + /// Use the `flatMap` method with a closure that may throw an error. For example: + /// + /// let possibleData: Result = .success(Data(...)) + /// let possibleObject = possibleData.flatMap { + /// try JSONSerialization.jsonObject(with: $0) + /// } + /// + /// - parameter transform: A closure that takes the success value of the instance. + /// + /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the + /// same failure. + public func flatMap(_ transform: (Value) throws -> T) -> Result { + switch self { + case .success(let value): + do { + return try .success(transform(value)) + } catch { + return .failure(error) + } + case .failure(let error): + return .failure(error) + } + } + + /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `mapError` function with a closure that does not throw. For example: + /// + /// let possibleData: Result = .failure(someError) + /// let withMyError: Result = possibleData.mapError { MyError.error($0) } + /// + /// - Parameter transform: A closure that takes the error of the instance. + /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns + /// the same instance. + public func mapError(_ transform: (Error) -> T) -> Result { + switch self { + case .failure(let error): + return .failure(transform(error)) + case .success: + return self + } + } + + /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `flatMapError` function with a closure that may throw an error. For example: + /// + /// let possibleData: Result = .success(Data(...)) + /// let possibleObject = possibleData.flatMapError { + /// try someFailableFunction(taking: $0) + /// } + /// + /// - Parameter transform: A throwing closure that takes the error of the instance. + /// + /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns + /// the same instance. + public func flatMapError(_ transform: (Error) throws -> T) -> Result { + switch self { + case .failure(let error): + do { + return try .failure(transform(error)) + } catch { + return .failure(error) + } + case .success: + return self + } + } + + /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter. + /// + /// Use the `withValue` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A closure that takes the success value of this instance. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func withValue(_ closure: (Value) -> Void) -> Result { + if case let .success(value) = self { closure(value) } + + return self + } + + /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter. + /// + /// Use the `withError` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A closure that takes the success value of this instance. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func withError(_ closure: (Error) -> Void) -> Result { + if case let .failure(error) = self { closure(error) } + + return self + } + + /// Evaluates the specified closure when the `Result` is a success. + /// + /// Use the `ifSuccess` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A `Void` closure. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func ifSuccess(_ closure: () -> Void) -> Result { + if isSuccess { closure() } + + return self + } + + /// Evaluates the specified closure when the `Result` is a failure. + /// + /// Use the `ifFailure` function to evaluate the passed closure without modifying the `Result` instance. + /// + /// - Parameter closure: A `Void` closure. + /// - Returns: This `Result` instance, unmodified. + @discardableResult + public func ifFailure(_ closure: () -> Void) -> Result { + if isFailure { closure() } + + return self + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/ServerTrustPolicy.swift b/SynchronyFinancial/Pods/Alamofire/Source/ServerTrustPolicy.swift new file mode 100644 index 0000000..7f44c8d --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/ServerTrustPolicy.swift @@ -0,0 +1,307 @@ +// +// ServerTrustPolicy.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host. +open class ServerTrustPolicyManager { + /// The dictionary of policies mapped to a particular host. + public let policies: [String: ServerTrustPolicy] + + /// Initializes the `ServerTrustPolicyManager` instance with the given policies. + /// + /// Since different servers and web services can have different leaf certificates, intermediate and even root + /// certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This + /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key + /// pinning for host3 and disabling evaluation for host4. + /// + /// - parameter policies: A dictionary of all policies mapped to a particular host. + /// + /// - returns: The new `ServerTrustPolicyManager` instance. + public init(policies: [String: ServerTrustPolicy]) { + self.policies = policies + } + + /// Returns the `ServerTrustPolicy` for the given host if applicable. + /// + /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override + /// this method and implement more complex mapping implementations such as wildcards. + /// + /// - parameter host: The host to use when searching for a matching policy. + /// + /// - returns: The server trust policy for the given host if found. + open func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? { + return policies[host] + } +} + +// MARK: - + +extension URLSession { + private struct AssociatedKeys { + static var managerKey = "URLSession.ServerTrustPolicyManager" + } + + var serverTrustPolicyManager: ServerTrustPolicyManager? { + get { + return objc_getAssociatedObject(self, &AssociatedKeys.managerKey) as? ServerTrustPolicyManager + } + set (manager) { + objc_setAssociatedObject(self, &AssociatedKeys.managerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } +} + +// MARK: - ServerTrustPolicy + +/// The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when +/// connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust +/// with a given set of criteria to determine whether the server trust is valid and the connection should be made. +/// +/// Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other +/// vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged +/// to route all communication over an HTTPS connection with pinning enabled. +/// +/// - performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to +/// validate the host provided by the challenge. Applications are encouraged to always +/// validate the host in production environments to guarantee the validity of the server's +/// certificate chain. +/// +/// - performRevokedEvaluation: Uses the default and revoked server trust evaluations allowing you to control whether to +/// validate the host provided by the challenge as well as specify the revocation flags for +/// testing for revoked certificates. Apple platforms did not start testing for revoked +/// certificates automatically until iOS 10.1, macOS 10.12 and tvOS 10.1 which is +/// demonstrated in our TLS tests. Applications are encouraged to always validate the host +/// in production environments to guarantee the validity of the server's certificate chain. +/// +/// - pinCertificates: Uses the pinned certificates to validate the server trust. The server trust is +/// considered valid if one of the pinned certificates match one of the server certificates. +/// By validating both the certificate chain and host, certificate pinning provides a very +/// secure form of server trust validation mitigating most, if not all, MITM attacks. +/// Applications are encouraged to always validate the host and require a valid certificate +/// chain in production environments. +/// +/// - pinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered +/// valid if one of the pinned public keys match one of the server certificate public keys. +/// By validating both the certificate chain and host, public key pinning provides a very +/// secure form of server trust validation mitigating most, if not all, MITM attacks. +/// Applications are encouraged to always validate the host and require a valid certificate +/// chain in production environments. +/// +/// - disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid. +/// +/// - customEvaluation: Uses the associated closure to evaluate the validity of the server trust. +public enum ServerTrustPolicy { + case performDefaultEvaluation(validateHost: Bool) + case performRevokedEvaluation(validateHost: Bool, revocationFlags: CFOptionFlags) + case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool) + case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool) + case disableEvaluation + case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool) + + // MARK: - Bundle Location + + /// Returns all certificates within the given bundle with a `.cer` file extension. + /// + /// - parameter bundle: The bundle to search for all `.cer` files. + /// + /// - returns: All certificates within the given bundle. + public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] { + var certificates: [SecCertificate] = [] + + let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in + bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil) + }.joined()) + + for path in paths { + if + let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData, + let certificate = SecCertificateCreateWithData(nil, certificateData) + { + certificates.append(certificate) + } + } + + return certificates + } + + /// Returns all public keys within the given bundle with a `.cer` file extension. + /// + /// - parameter bundle: The bundle to search for all `*.cer` files. + /// + /// - returns: All public keys within the given bundle. + public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] { + var publicKeys: [SecKey] = [] + + for certificate in certificates(in: bundle) { + if let publicKey = publicKey(for: certificate) { + publicKeys.append(publicKey) + } + } + + return publicKeys + } + + // MARK: - Evaluation + + /// Evaluates whether the server trust is valid for the given host. + /// + /// - parameter serverTrust: The server trust to evaluate. + /// - parameter host: The host of the challenge protection space. + /// + /// - returns: Whether the server trust is valid. + public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool { + var serverTrustIsValid = false + + switch self { + case let .performDefaultEvaluation(validateHost): + let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + SecTrustSetPolicies(serverTrust, policy) + + serverTrustIsValid = trustIsValid(serverTrust) + case let .performRevokedEvaluation(validateHost, revocationFlags): + let defaultPolicy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + let revokedPolicy = SecPolicyCreateRevocation(revocationFlags) + SecTrustSetPolicies(serverTrust, [defaultPolicy, revokedPolicy] as CFTypeRef) + + serverTrustIsValid = trustIsValid(serverTrust) + case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost): + if validateCertificateChain { + let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + SecTrustSetPolicies(serverTrust, policy) + + SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray) + SecTrustSetAnchorCertificatesOnly(serverTrust, true) + + serverTrustIsValid = trustIsValid(serverTrust) + } else { + let serverCertificatesDataArray = certificateData(for: serverTrust) + let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates) + + outerLoop: for serverCertificateData in serverCertificatesDataArray { + for pinnedCertificateData in pinnedCertificatesDataArray { + if serverCertificateData == pinnedCertificateData { + serverTrustIsValid = true + break outerLoop + } + } + } + } + case let .pinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost): + var certificateChainEvaluationPassed = true + + if validateCertificateChain { + let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) + SecTrustSetPolicies(serverTrust, policy) + + certificateChainEvaluationPassed = trustIsValid(serverTrust) + } + + if certificateChainEvaluationPassed { + outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: serverTrust) as [AnyObject] { + for pinnedPublicKey in pinnedPublicKeys as [AnyObject] { + if serverPublicKey.isEqual(pinnedPublicKey) { + serverTrustIsValid = true + break outerLoop + } + } + } + } + case .disableEvaluation: + serverTrustIsValid = true + case let .customEvaluation(closure): + serverTrustIsValid = closure(serverTrust, host) + } + + return serverTrustIsValid + } + + // MARK: - Private - Trust Validation + + private func trustIsValid(_ trust: SecTrust) -> Bool { + var isValid = false + + var result = SecTrustResultType.invalid + let status = SecTrustEvaluate(trust, &result) + + if status == errSecSuccess { + let unspecified = SecTrustResultType.unspecified + let proceed = SecTrustResultType.proceed + + + isValid = result == unspecified || result == proceed + } + + return isValid + } + + // MARK: - Private - Certificate Data + + private func certificateData(for trust: SecTrust) -> [Data] { + var certificates: [SecCertificate] = [] + + for index in 0.. [Data] { + return certificates.map { SecCertificateCopyData($0) as Data } + } + + // MARK: - Private - Public Key Extraction + + private static func publicKeys(for trust: SecTrust) -> [SecKey] { + var publicKeys: [SecKey] = [] + + for index in 0.. SecKey? { + var publicKey: SecKey? + + let policy = SecPolicyCreateBasicX509() + var trust: SecTrust? + let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) + + if let trust = trust, trustCreationStatus == errSecSuccess { + publicKey = SecTrustCopyPublicKey(trust) + } + + return publicKey + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/SessionDelegate.swift b/SynchronyFinancial/Pods/Alamofire/Source/SessionDelegate.swift new file mode 100644 index 0000000..03bcb7c --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/SessionDelegate.swift @@ -0,0 +1,725 @@ +// +// SessionDelegate.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Responsible for handling all delegate callbacks for the underlying session. +open class SessionDelegate: NSObject { + + // MARK: URLSessionDelegate Overrides + + /// Overrides default behavior for URLSessionDelegate method `urlSession(_:didBecomeInvalidWithError:)`. + open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)? + + /// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`. + open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? + + /// Overrides all behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)` and requires the caller to call the `completionHandler`. + open var sessionDidReceiveChallengeWithCompletion: ((URLSession, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionDelegate method `urlSessionDidFinishEvents(forBackgroundURLSession:)`. + open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)? + + // MARK: URLSessionTaskDelegate Overrides + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`. + open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)? + + /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` and + /// requires the caller to call the `completionHandler`. + open var taskWillPerformHTTPRedirectionWithCompletion: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest, @escaping (URLRequest?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)`. + open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? + + /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)` and + /// requires the caller to call the `completionHandler`. + open var taskDidReceiveChallengeWithCompletion: ((URLSession, URLSessionTask, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)`. + open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)? + + /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)` and + /// requires the caller to call the `completionHandler`. + open var taskNeedNewBodyStreamWithCompletion: ((URLSession, URLSessionTask, @escaping (InputStream?) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)`. + open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)? + + /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didCompleteWithError:)`. + open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)? + + // MARK: URLSessionDataDelegate Overrides + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)`. + open var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)? + + /// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)` and + /// requires caller to call the `completionHandler`. + open var dataTaskDidReceiveResponseWithCompletion: ((URLSession, URLSessionDataTask, URLResponse, @escaping (URLSession.ResponseDisposition) -> Void) -> Void)? + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didBecome:)`. + open var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)? + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:)`. + open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)? + + /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)`. + open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)? + + /// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)` and + /// requires caller to call the `completionHandler`. + open var dataTaskWillCacheResponseWithCompletion: ((URLSession, URLSessionDataTask, CachedURLResponse, @escaping (CachedURLResponse?) -> Void) -> Void)? + + // MARK: URLSessionDownloadDelegate Overrides + + /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didFinishDownloadingTo:)`. + open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)? + + /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`. + open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)? + + /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)`. + open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)? + + // MARK: URLSessionStreamDelegate Overrides + +#if !os(watchOS) + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:readClosedFor:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)? { + get { + return _streamTaskReadClosed as? (URLSession, URLSessionStreamTask) -> Void + } + set { + _streamTaskReadClosed = newValue + } + } + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:writeClosedFor:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskWriteClosed: ((URLSession, URLSessionStreamTask) -> Void)? { + get { + return _streamTaskWriteClosed as? (URLSession, URLSessionStreamTask) -> Void + } + set { + _streamTaskWriteClosed = newValue + } + } + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:betterRouteDiscoveredFor:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskBetterRouteDiscovered: ((URLSession, URLSessionStreamTask) -> Void)? { + get { + return _streamTaskBetterRouteDiscovered as? (URLSession, URLSessionStreamTask) -> Void + } + set { + _streamTaskBetterRouteDiscovered = newValue + } + } + + /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:streamTask:didBecome:outputStream:)`. + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open var streamTaskDidBecomeInputAndOutputStreams: ((URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void)? { + get { + return _streamTaskDidBecomeInputStream as? (URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void + } + set { + _streamTaskDidBecomeInputStream = newValue + } + } + + var _streamTaskReadClosed: Any? + var _streamTaskWriteClosed: Any? + var _streamTaskBetterRouteDiscovered: Any? + var _streamTaskDidBecomeInputStream: Any? + +#endif + + // MARK: Properties + + var retrier: RequestRetrier? + weak var sessionManager: SessionManager? + + var requests: [Int: Request] = [:] + private let lock = NSLock() + + /// Access the task delegate for the specified task in a thread-safe manner. + open subscript(task: URLSessionTask) -> Request? { + get { + lock.lock() ; defer { lock.unlock() } + return requests[task.taskIdentifier] + } + set { + lock.lock() ; defer { lock.unlock() } + requests[task.taskIdentifier] = newValue + } + } + + // MARK: Lifecycle + + /// Initializes the `SessionDelegate` instance. + /// + /// - returns: The new `SessionDelegate` instance. + public override init() { + super.init() + } + + // MARK: NSObject Overrides + + /// Returns a `Bool` indicating whether the `SessionDelegate` implements or inherits a method that can respond + /// to a specified message. + /// + /// - parameter selector: A selector that identifies a message. + /// + /// - returns: `true` if the receiver implements or inherits a method that can respond to selector, otherwise `false`. + open override func responds(to selector: Selector) -> Bool { + #if !os(macOS) + if selector == #selector(URLSessionDelegate.urlSessionDidFinishEvents(forBackgroundURLSession:)) { + return sessionDidFinishEventsForBackgroundURLSession != nil + } + #endif + + #if !os(watchOS) + if #available(iOS 9.0, macOS 10.11, tvOS 9.0, *) { + switch selector { + case #selector(URLSessionStreamDelegate.urlSession(_:readClosedFor:)): + return streamTaskReadClosed != nil + case #selector(URLSessionStreamDelegate.urlSession(_:writeClosedFor:)): + return streamTaskWriteClosed != nil + case #selector(URLSessionStreamDelegate.urlSession(_:betterRouteDiscoveredFor:)): + return streamTaskBetterRouteDiscovered != nil + case #selector(URLSessionStreamDelegate.urlSession(_:streamTask:didBecome:outputStream:)): + return streamTaskDidBecomeInputAndOutputStreams != nil + default: + break + } + } + #endif + + switch selector { + case #selector(URLSessionDelegate.urlSession(_:didBecomeInvalidWithError:)): + return sessionDidBecomeInvalidWithError != nil + case #selector(URLSessionDelegate.urlSession(_:didReceive:completionHandler:)): + return (sessionDidReceiveChallenge != nil || sessionDidReceiveChallengeWithCompletion != nil) + case #selector(URLSessionTaskDelegate.urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)): + return (taskWillPerformHTTPRedirection != nil || taskWillPerformHTTPRedirectionWithCompletion != nil) + case #selector(URLSessionDataDelegate.urlSession(_:dataTask:didReceive:completionHandler:)): + return (dataTaskDidReceiveResponse != nil || dataTaskDidReceiveResponseWithCompletion != nil) + default: + return type(of: self).instancesRespond(to: selector) + } + } +} + +// MARK: - URLSessionDelegate + +extension SessionDelegate: URLSessionDelegate { + /// Tells the delegate that the session has been invalidated. + /// + /// - parameter session: The session object that was invalidated. + /// - parameter error: The error that caused invalidation, or nil if the invalidation was explicit. + open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) { + sessionDidBecomeInvalidWithError?(session, error) + } + + /// Requests credentials from the delegate in response to a session-level authentication request from the + /// remote server. + /// + /// - parameter session: The session containing the task that requested authentication. + /// - parameter challenge: An object that contains the request for authentication. + /// - parameter completionHandler: A handler that your delegate method must call providing the disposition + /// and credential. + open func urlSession( + _ session: URLSession, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + { + guard sessionDidReceiveChallengeWithCompletion == nil else { + sessionDidReceiveChallengeWithCompletion?(session, challenge, completionHandler) + return + } + + var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling + var credential: URLCredential? + + if let sessionDidReceiveChallenge = sessionDidReceiveChallenge { + (disposition, credential) = sessionDidReceiveChallenge(session, challenge) + } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { + let host = challenge.protectionSpace.host + + if + let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host), + let serverTrust = challenge.protectionSpace.serverTrust + { + if serverTrustPolicy.evaluate(serverTrust, forHost: host) { + disposition = .useCredential + credential = URLCredential(trust: serverTrust) + } else { + disposition = .cancelAuthenticationChallenge + } + } + } + + completionHandler(disposition, credential) + } + +#if !os(macOS) + + /// Tells the delegate that all messages enqueued for a session have been delivered. + /// + /// - parameter session: The session that no longer has any outstanding requests. + open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { + sessionDidFinishEventsForBackgroundURLSession?(session) + } + +#endif +} + +// MARK: - URLSessionTaskDelegate + +extension SessionDelegate: URLSessionTaskDelegate { + /// Tells the delegate that the remote server requested an HTTP redirect. + /// + /// - parameter session: The session containing the task whose request resulted in a redirect. + /// - parameter task: The task whose request resulted in a redirect. + /// - parameter response: An object containing the server’s response to the original request. + /// - parameter request: A URL request object filled out with the new location. + /// - parameter completionHandler: A closure that your handler should call with either the value of the request + /// parameter, a modified URL request object, or NULL to refuse the redirect and + /// return the body of the redirect response. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + guard taskWillPerformHTTPRedirectionWithCompletion == nil else { + taskWillPerformHTTPRedirectionWithCompletion?(session, task, response, request, completionHandler) + return + } + + var redirectRequest: URLRequest? = request + + if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection { + redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request) + } + + completionHandler(redirectRequest) + } + + /// Requests credentials from the delegate in response to an authentication request from the remote server. + /// + /// - parameter session: The session containing the task whose request requires authentication. + /// - parameter task: The task whose request requires authentication. + /// - parameter challenge: An object that contains the request for authentication. + /// - parameter completionHandler: A handler that your delegate method must call providing the disposition + /// and credential. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + { + guard taskDidReceiveChallengeWithCompletion == nil else { + taskDidReceiveChallengeWithCompletion?(session, task, challenge, completionHandler) + return + } + + if let taskDidReceiveChallenge = taskDidReceiveChallenge { + let result = taskDidReceiveChallenge(session, task, challenge) + completionHandler(result.0, result.1) + } else if let delegate = self[task]?.delegate { + delegate.urlSession( + session, + task: task, + didReceive: challenge, + completionHandler: completionHandler + ) + } else { + urlSession(session, didReceive: challenge, completionHandler: completionHandler) + } + } + + /// Tells the delegate when a task requires a new request body stream to send to the remote server. + /// + /// - parameter session: The session containing the task that needs a new body stream. + /// - parameter task: The task that needs a new body stream. + /// - parameter completionHandler: A completion handler that your delegate method should call with the new body stream. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) + { + guard taskNeedNewBodyStreamWithCompletion == nil else { + taskNeedNewBodyStreamWithCompletion?(session, task, completionHandler) + return + } + + if let taskNeedNewBodyStream = taskNeedNewBodyStream { + completionHandler(taskNeedNewBodyStream(session, task)) + } else if let delegate = self[task]?.delegate { + delegate.urlSession(session, task: task, needNewBodyStream: completionHandler) + } + } + + /// Periodically informs the delegate of the progress of sending body content to the server. + /// + /// - parameter session: The session containing the data task. + /// - parameter task: The data task. + /// - parameter bytesSent: The number of bytes sent since the last time this delegate method was called. + /// - parameter totalBytesSent: The total number of bytes sent so far. + /// - parameter totalBytesExpectedToSend: The expected length of the body data. + open func urlSession( + _ session: URLSession, + task: URLSessionTask, + didSendBodyData bytesSent: Int64, + totalBytesSent: Int64, + totalBytesExpectedToSend: Int64) + { + if let taskDidSendBodyData = taskDidSendBodyData { + taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) + } else if let delegate = self[task]?.delegate as? UploadTaskDelegate { + delegate.URLSession( + session, + task: task, + didSendBodyData: bytesSent, + totalBytesSent: totalBytesSent, + totalBytesExpectedToSend: totalBytesExpectedToSend + ) + } + } + +#if !os(watchOS) + + /// Tells the delegate that the session finished collecting metrics for the task. + /// + /// - parameter session: The session collecting the metrics. + /// - parameter task: The task whose metrics have been collected. + /// - parameter metrics: The collected metrics. + @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) + @objc(URLSession:task:didFinishCollectingMetrics:) + open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { + self[task]?.delegate.metrics = metrics + } + +#endif + + /// Tells the delegate that the task finished transferring data. + /// + /// - parameter session: The session containing the task whose request finished transferring data. + /// - parameter task: The task whose request finished transferring data. + /// - parameter error: If an error occurred, an error object indicating how the transfer failed, otherwise nil. + open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + /// Executed after it is determined that the request is not going to be retried + let completeTask: (URLSession, URLSessionTask, Error?) -> Void = { [weak self] session, task, error in + guard let strongSelf = self else { return } + + strongSelf.taskDidComplete?(session, task, error) + + strongSelf[task]?.delegate.urlSession(session, task: task, didCompleteWithError: error) + + var userInfo: [String: Any] = [Notification.Key.Task: task] + + if let data = (strongSelf[task]?.delegate as? DataTaskDelegate)?.data { + userInfo[Notification.Key.ResponseData] = data + } + + NotificationCenter.default.post( + name: Notification.Name.Task.DidComplete, + object: strongSelf, + userInfo: userInfo + ) + + strongSelf[task] = nil + } + + guard let request = self[task], let sessionManager = sessionManager else { + completeTask(session, task, error) + return + } + + // Run all validations on the request before checking if an error occurred + request.validations.forEach { $0() } + + // Determine whether an error has occurred + var error: Error? = error + + if request.delegate.error != nil { + error = request.delegate.error + } + + /// If an error occurred and the retrier is set, asynchronously ask the retrier if the request + /// should be retried. Otherwise, complete the task by notifying the task delegate. + if let retrier = retrier, let error = error { + retrier.should(sessionManager, retry: request, with: error) { [weak self] shouldRetry, timeDelay in + guard shouldRetry else { completeTask(session, task, error) ; return } + + DispatchQueue.utility.after(timeDelay) { [weak self] in + guard let strongSelf = self else { return } + + let retrySucceeded = strongSelf.sessionManager?.retry(request) ?? false + + if retrySucceeded, let task = request.task { + strongSelf[task] = request + return + } else { + completeTask(session, task, error) + } + } + } + } else { + completeTask(session, task, error) + } + } +} + +// MARK: - URLSessionDataDelegate + +extension SessionDelegate: URLSessionDataDelegate { + /// Tells the delegate that the data task received the initial reply (headers) from the server. + /// + /// - parameter session: The session containing the data task that received an initial reply. + /// - parameter dataTask: The data task that received an initial reply. + /// - parameter response: A URL response object populated with headers. + /// - parameter completionHandler: A completion handler that your code calls to continue the transfer, passing a + /// constant to indicate whether the transfer should continue as a data task or + /// should become a download task. + open func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didReceive response: URLResponse, + completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) + { + guard dataTaskDidReceiveResponseWithCompletion == nil else { + dataTaskDidReceiveResponseWithCompletion?(session, dataTask, response, completionHandler) + return + } + + var disposition: URLSession.ResponseDisposition = .allow + + if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse { + disposition = dataTaskDidReceiveResponse(session, dataTask, response) + } + + completionHandler(disposition) + } + + /// Tells the delegate that the data task was changed to a download task. + /// + /// - parameter session: The session containing the task that was replaced by a download task. + /// - parameter dataTask: The data task that was replaced by a download task. + /// - parameter downloadTask: The new download task that replaced the data task. + open func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didBecome downloadTask: URLSessionDownloadTask) + { + if let dataTaskDidBecomeDownloadTask = dataTaskDidBecomeDownloadTask { + dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask) + } else { + self[downloadTask]?.delegate = DownloadTaskDelegate(task: downloadTask) + } + } + + /// Tells the delegate that the data task has received some of the expected data. + /// + /// - parameter session: The session containing the data task that provided data. + /// - parameter dataTask: The data task that provided data. + /// - parameter data: A data object containing the transferred data. + open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + if let dataTaskDidReceiveData = dataTaskDidReceiveData { + dataTaskDidReceiveData(session, dataTask, data) + } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate { + delegate.urlSession(session, dataTask: dataTask, didReceive: data) + } + } + + /// Asks the delegate whether the data (or upload) task should store the response in the cache. + /// + /// - parameter session: The session containing the data (or upload) task. + /// - parameter dataTask: The data (or upload) task. + /// - parameter proposedResponse: The default caching behavior. This behavior is determined based on the current + /// caching policy and the values of certain received headers, such as the Pragma + /// and Cache-Control headers. + /// - parameter completionHandler: A block that your handler must call, providing either the original proposed + /// response, a modified version of that response, or NULL to prevent caching the + /// response. If your delegate implements this method, it must call this completion + /// handler; otherwise, your app leaks memory. + open func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + willCacheResponse proposedResponse: CachedURLResponse, + completionHandler: @escaping (CachedURLResponse?) -> Void) + { + guard dataTaskWillCacheResponseWithCompletion == nil else { + dataTaskWillCacheResponseWithCompletion?(session, dataTask, proposedResponse, completionHandler) + return + } + + if let dataTaskWillCacheResponse = dataTaskWillCacheResponse { + completionHandler(dataTaskWillCacheResponse(session, dataTask, proposedResponse)) + } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate { + delegate.urlSession( + session, + dataTask: dataTask, + willCacheResponse: proposedResponse, + completionHandler: completionHandler + ) + } else { + completionHandler(proposedResponse) + } + } +} + +// MARK: - URLSessionDownloadDelegate + +extension SessionDelegate: URLSessionDownloadDelegate { + /// Tells the delegate that a download task has finished downloading. + /// + /// - parameter session: The session containing the download task that finished. + /// - parameter downloadTask: The download task that finished. + /// - parameter location: A file URL for the temporary file. Because the file is temporary, you must either + /// open the file for reading or move it to a permanent location in your app’s sandbox + /// container directory before returning from this delegate method. + open func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didFinishDownloadingTo location: URL) + { + if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL { + downloadTaskDidFinishDownloadingToURL(session, downloadTask, location) + } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate { + delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location) + } + } + + /// Periodically informs the delegate about the download’s progress. + /// + /// - parameter session: The session containing the download task. + /// - parameter downloadTask: The download task. + /// - parameter bytesWritten: The number of bytes transferred since the last time this delegate + /// method was called. + /// - parameter totalBytesWritten: The total number of bytes transferred so far. + /// - parameter totalBytesExpectedToWrite: The expected length of the file, as provided by the Content-Length + /// header. If this header was not provided, the value is + /// `NSURLSessionTransferSizeUnknown`. + open func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didWriteData bytesWritten: Int64, + totalBytesWritten: Int64, + totalBytesExpectedToWrite: Int64) + { + if let downloadTaskDidWriteData = downloadTaskDidWriteData { + downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) + } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate { + delegate.urlSession( + session, + downloadTask: downloadTask, + didWriteData: bytesWritten, + totalBytesWritten: totalBytesWritten, + totalBytesExpectedToWrite: totalBytesExpectedToWrite + ) + } + } + + /// Tells the delegate that the download task has resumed downloading. + /// + /// - parameter session: The session containing the download task that finished. + /// - parameter downloadTask: The download task that resumed. See explanation in the discussion. + /// - parameter fileOffset: If the file's cache policy or last modified date prevents reuse of the + /// existing content, then this value is zero. Otherwise, this value is an + /// integer representing the number of bytes on disk that do not need to be + /// retrieved again. + /// - parameter expectedTotalBytes: The expected length of the file, as provided by the Content-Length header. + /// If this header was not provided, the value is NSURLSessionTransferSizeUnknown. + open func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didResumeAtOffset fileOffset: Int64, + expectedTotalBytes: Int64) + { + if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { + downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) + } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate { + delegate.urlSession( + session, + downloadTask: downloadTask, + didResumeAtOffset: fileOffset, + expectedTotalBytes: expectedTotalBytes + ) + } + } +} + +// MARK: - URLSessionStreamDelegate + +#if !os(watchOS) + +@available(iOS 9.0, macOS 10.11, tvOS 9.0, *) +extension SessionDelegate: URLSessionStreamDelegate { + /// Tells the delegate that the read side of the connection has been closed. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + open func urlSession(_ session: URLSession, readClosedFor streamTask: URLSessionStreamTask) { + streamTaskReadClosed?(session, streamTask) + } + + /// Tells the delegate that the write side of the connection has been closed. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + open func urlSession(_ session: URLSession, writeClosedFor streamTask: URLSessionStreamTask) { + streamTaskWriteClosed?(session, streamTask) + } + + /// Tells the delegate that the system has determined that a better route to the host is available. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + open func urlSession(_ session: URLSession, betterRouteDiscoveredFor streamTask: URLSessionStreamTask) { + streamTaskBetterRouteDiscovered?(session, streamTask) + } + + /// Tells the delegate that the stream task has been completed and provides the unopened stream objects. + /// + /// - parameter session: The session. + /// - parameter streamTask: The stream task. + /// - parameter inputStream: The new input stream. + /// - parameter outputStream: The new output stream. + open func urlSession( + _ session: URLSession, + streamTask: URLSessionStreamTask, + didBecome inputStream: InputStream, + outputStream: OutputStream) + { + streamTaskDidBecomeInputAndOutputStreams?(session, streamTask, inputStream, outputStream) + } +} + +#endif diff --git a/SynchronyFinancial/Pods/Alamofire/Source/SessionManager.swift b/SynchronyFinancial/Pods/Alamofire/Source/SessionManager.swift new file mode 100644 index 0000000..8779efd --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/SessionManager.swift @@ -0,0 +1,896 @@ +// +// SessionManager.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Responsible for creating and managing `Request` objects, as well as their underlying `NSURLSession`. +open class SessionManager { + + // MARK: - Helper Types + + /// Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as + /// associated values. + /// + /// - Success: Represents a successful `MultipartFormData` encoding and contains the new `UploadRequest` along with + /// streaming information. + /// - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding + /// error. + public enum MultipartFormDataEncodingResult { + case success(request: UploadRequest, streamingFromDisk: Bool, streamFileURL: URL?) + case failure(Error) + } + + // MARK: - Properties + + /// A default instance of `SessionManager`, used by top-level Alamofire request methods, and suitable for use + /// directly for any ad hoc requests. + public static let `default`: SessionManager = { + let configuration = URLSessionConfiguration.default + configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders + + return SessionManager(configuration: configuration) + }() + + /// Creates default values for the "Accept-Encoding", "Accept-Language" and "User-Agent" headers. + public static let defaultHTTPHeaders: HTTPHeaders = { + // Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3 + let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5" + + // Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5 + let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in + let quality = 1.0 - (Double(index) * 0.1) + return "\(languageCode);q=\(quality)" + }.joined(separator: ", ") + + // User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3 + // Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0` + let userAgent: String = { + if let info = Bundle.main.infoDictionary { + let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown" + let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown" + let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown" + let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown" + + let osNameVersion: String = { + let version = ProcessInfo.processInfo.operatingSystemVersion + let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)" + + let osName: String = { + #if os(iOS) + return "iOS" + #elseif os(watchOS) + return "watchOS" + #elseif os(tvOS) + return "tvOS" + #elseif os(macOS) + return "OS X" + #elseif os(Linux) + return "Linux" + #else + return "Unknown" + #endif + }() + + return "\(osName) \(versionString)" + }() + + let alamofireVersion: String = { + guard + let afInfo = Bundle(for: SessionManager.self).infoDictionary, + let build = afInfo["CFBundleShortVersionString"] + else { return "Unknown" } + + return "Alamofire/\(build)" + }() + + return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)" + } + + return "Alamofire" + }() + + return [ + "Accept-Encoding": acceptEncoding, + "Accept-Language": acceptLanguage, + "User-Agent": userAgent + ] + }() + + /// Default memory threshold used when encoding `MultipartFormData` in bytes. + public static let multipartFormDataEncodingMemoryThreshold: UInt64 = 10_000_000 + + /// The underlying session. + public let session: URLSession + + /// The session delegate handling all the task and session delegate callbacks. + public let delegate: SessionDelegate + + /// Whether to start requests immediately after being constructed. `true` by default. + open var startRequestsImmediately: Bool = true + + /// The request adapter called each time a new request is created. + open var adapter: RequestAdapter? + + /// The request retrier called each time a request encounters an error to determine whether to retry the request. + open var retrier: RequestRetrier? { + get { return delegate.retrier } + set { delegate.retrier = newValue } + } + + /// The background completion handler closure provided by the UIApplicationDelegate + /// `application:handleEventsForBackgroundURLSession:completionHandler:` method. By setting the background + /// completion handler, the SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` closure implementation + /// will automatically call the handler. + /// + /// If you need to handle your own events before the handler is called, then you need to override the + /// SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` and manually call the handler when finished. + /// + /// `nil` by default. + open var backgroundCompletionHandler: (() -> Void)? + + let queue = DispatchQueue(label: "org.alamofire.session-manager." + UUID().uuidString) + + // MARK: - Lifecycle + + /// Creates an instance with the specified `configuration`, `delegate` and `serverTrustPolicyManager`. + /// + /// - parameter configuration: The configuration used to construct the managed session. + /// `URLSessionConfiguration.default` by default. + /// - parameter delegate: The delegate used when initializing the session. `SessionDelegate()` by + /// default. + /// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust + /// challenges. `nil` by default. + /// + /// - returns: The new `SessionManager` instance. + public init( + configuration: URLSessionConfiguration = URLSessionConfiguration.default, + delegate: SessionDelegate = SessionDelegate(), + serverTrustPolicyManager: ServerTrustPolicyManager? = nil) + { + self.delegate = delegate + self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil) + + commonInit(serverTrustPolicyManager: serverTrustPolicyManager) + } + + /// Creates an instance with the specified `session`, `delegate` and `serverTrustPolicyManager`. + /// + /// - parameter session: The URL session. + /// - parameter delegate: The delegate of the URL session. Must equal the URL session's delegate. + /// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust + /// challenges. `nil` by default. + /// + /// - returns: The new `SessionManager` instance if the URL session's delegate matches; `nil` otherwise. + public init?( + session: URLSession, + delegate: SessionDelegate, + serverTrustPolicyManager: ServerTrustPolicyManager? = nil) + { + guard delegate === session.delegate else { return nil } + + self.delegate = delegate + self.session = session + + commonInit(serverTrustPolicyManager: serverTrustPolicyManager) + } + + private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?) { + session.serverTrustPolicyManager = serverTrustPolicyManager + + delegate.sessionManager = self + + delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in + guard let strongSelf = self else { return } + DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() } + } + } + + deinit { + session.invalidateAndCancel() + } + + // MARK: - Data Request + + /// Creates a `DataRequest` to retrieve the contents of the specified `url`, `method`, `parameters`, `encoding` + /// and `headers`. + /// + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.get` by default. + /// - parameter parameters: The parameters. `nil` by default. + /// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `DataRequest`. + @discardableResult + open func request( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil) + -> DataRequest + { + var originalRequest: URLRequest? + + do { + originalRequest = try URLRequest(url: url, method: method, headers: headers) + let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters) + return request(encodedURLRequest) + } catch { + return request(originalRequest, failedWith: error) + } + } + + /// Creates a `DataRequest` to retrieve the contents of a URL based on the specified `urlRequest`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `DataRequest`. + @discardableResult + open func request(_ urlRequest: URLRequestConvertible) -> DataRequest { + var originalRequest: URLRequest? + + do { + originalRequest = try urlRequest.asURLRequest() + let originalTask = DataRequest.Requestable(urlRequest: originalRequest!) + + let task = try originalTask.task(session: session, adapter: adapter, queue: queue) + let request = DataRequest(session: session, requestTask: .data(originalTask, task)) + + delegate[task] = request + + if startRequestsImmediately { request.resume() } + + return request + } catch { + return request(originalRequest, failedWith: error) + } + } + + // MARK: Private - Request Implementation + + private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest { + var requestTask: Request.RequestTask = .data(nil, nil) + + if let urlRequest = urlRequest { + let originalTask = DataRequest.Requestable(urlRequest: urlRequest) + requestTask = .data(originalTask, nil) + } + + let underlyingError = error.underlyingAdaptError ?? error + let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError) + + if let retrier = retrier, error is AdaptError { + allowRetrier(retrier, toRetry: request, with: underlyingError) + } else { + if startRequestsImmediately { request.resume() } + } + + return request + } + + // MARK: - Download Request + + // MARK: URL Request + + /// Creates a `DownloadRequest` to retrieve the contents the specified `url`, `method`, `parameters`, `encoding`, + /// `headers` and save them to the `destination`. + /// + /// If `destination` is not specified, the contents will remain in the temporary location determined by the + /// underlying URL session. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.get` by default. + /// - parameter parameters: The parameters. `nil` by default. + /// - parameter encoding: The parameter encoding. `URLEncoding.default` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. + /// + /// - returns: The created `DownloadRequest`. + @discardableResult + open func download( + _ url: URLConvertible, + method: HTTPMethod = .get, + parameters: Parameters? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: HTTPHeaders? = nil, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + let encodedURLRequest = try encoding.encode(urlRequest, with: parameters) + return download(encodedURLRequest, to: destination) + } catch { + return download(nil, to: destination, failedWith: error) + } + } + + /// Creates a `DownloadRequest` to retrieve the contents of a URL based on the specified `urlRequest` and save + /// them to the `destination`. + /// + /// If `destination` is not specified, the contents will remain in the temporary location determined by the + /// underlying URL session. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter urlRequest: The URL request + /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. + /// + /// - returns: The created `DownloadRequest`. + @discardableResult + open func download( + _ urlRequest: URLRequestConvertible, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest + { + do { + let urlRequest = try urlRequest.asURLRequest() + return download(.request(urlRequest), to: destination) + } catch { + return download(nil, to: destination, failedWith: error) + } + } + + // MARK: Resume Data + + /// Creates a `DownloadRequest` from the `resumeData` produced from a previous request cancellation to retrieve + /// the contents of the original request and save them to the `destination`. + /// + /// If `destination` is not specified, the contents will remain in the temporary location determined by the + /// underlying URL session. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken + /// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the + /// data is written incorrectly and will always fail to resume the download. For more information about the bug and + /// possible workarounds, please refer to the following Stack Overflow post: + /// + /// - http://stackoverflow.com/a/39347461/1342462 + /// + /// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask` + /// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for + /// additional information. + /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default. + /// + /// - returns: The created `DownloadRequest`. + @discardableResult + open func download( + resumingWith resumeData: Data, + to destination: DownloadRequest.DownloadFileDestination? = nil) + -> DownloadRequest + { + return download(.resumeData(resumeData), to: destination) + } + + // MARK: Private - Download Implementation + + private func download( + _ downloadable: DownloadRequest.Downloadable, + to destination: DownloadRequest.DownloadFileDestination?) + -> DownloadRequest + { + do { + let task = try downloadable.task(session: session, adapter: adapter, queue: queue) + let download = DownloadRequest(session: session, requestTask: .download(downloadable, task)) + + download.downloadDelegate.destination = destination + + delegate[task] = download + + if startRequestsImmediately { download.resume() } + + return download + } catch { + return download(downloadable, to: destination, failedWith: error) + } + } + + private func download( + _ downloadable: DownloadRequest.Downloadable?, + to destination: DownloadRequest.DownloadFileDestination?, + failedWith error: Error) + -> DownloadRequest + { + var downloadTask: Request.RequestTask = .download(nil, nil) + + if let downloadable = downloadable { + downloadTask = .download(downloadable, nil) + } + + let underlyingError = error.underlyingAdaptError ?? error + + let download = DownloadRequest(session: session, requestTask: downloadTask, error: underlyingError) + download.downloadDelegate.destination = destination + + if let retrier = retrier, error is AdaptError { + allowRetrier(retrier, toRetry: download, with: underlyingError) + } else { + if startRequestsImmediately { download.resume() } + } + + return download + } + + // MARK: - Upload Request + + // MARK: File + + /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `file`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter file: The file to upload. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload( + _ fileURL: URL, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + return upload(fileURL, with: urlRequest) + } catch { + return upload(nil, failedWith: error) + } + } + + /// Creates a `UploadRequest` from the specified `urlRequest` for uploading the `file`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter file: The file to upload. + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest { + do { + let urlRequest = try urlRequest.asURLRequest() + return upload(.file(fileURL, urlRequest)) + } catch { + return upload(nil, failedWith: error) + } + } + + // MARK: Data + + /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `data`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter data: The data to upload. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload( + _ data: Data, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + return upload(data, with: urlRequest) + } catch { + return upload(nil, failedWith: error) + } + } + + /// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `data`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter data: The data to upload. + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest { + do { + let urlRequest = try urlRequest.asURLRequest() + return upload(.data(data, urlRequest)) + } catch { + return upload(nil, failedWith: error) + } + } + + // MARK: InputStream + + /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `stream`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter stream: The stream to upload. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload( + _ stream: InputStream, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil) + -> UploadRequest + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + return upload(stream, with: urlRequest) + } catch { + return upload(nil, failedWith: error) + } + } + + /// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `stream`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter stream: The stream to upload. + /// - parameter urlRequest: The URL request. + /// + /// - returns: The created `UploadRequest`. + @discardableResult + open func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest { + do { + let urlRequest = try urlRequest.asURLRequest() + return upload(.stream(stream, urlRequest)) + } catch { + return upload(nil, failedWith: error) + } + } + + // MARK: MultipartFormData + + /// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new + /// `UploadRequest` using the `url`, `method` and `headers`. + /// + /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative + /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most + /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to + /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory + /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be + /// used for larger payloads such as video content. + /// + /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory + /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, + /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk + /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding + /// technique was used. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. + /// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. + /// `multipartFormDataEncodingMemoryThreshold` by default. + /// - parameter url: The URL. + /// - parameter method: The HTTP method. `.post` by default. + /// - parameter headers: The HTTP headers. `nil` by default. + /// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. + open func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + to url: URLConvertible, + method: HTTPMethod = .post, + headers: HTTPHeaders? = nil, + encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?) + { + do { + let urlRequest = try URLRequest(url: url, method: method, headers: headers) + + return upload( + multipartFormData: multipartFormData, + usingThreshold: encodingMemoryThreshold, + with: urlRequest, + encodingCompletion: encodingCompletion + ) + } catch { + DispatchQueue.main.async { encodingCompletion?(.failure(error)) } + } + } + + /// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new + /// `UploadRequest` using the `urlRequest`. + /// + /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative + /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most + /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to + /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory + /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be + /// used for larger payloads such as video content. + /// + /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory + /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`, + /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk + /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding + /// technique was used. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter multipartFormData: The closure used to append body parts to the `MultipartFormData`. + /// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes. + /// `multipartFormDataEncodingMemoryThreshold` by default. + /// - parameter urlRequest: The URL request. + /// - parameter encodingCompletion: The closure called when the `MultipartFormData` encoding is complete. + open func upload( + multipartFormData: @escaping (MultipartFormData) -> Void, + usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold, + with urlRequest: URLRequestConvertible, + encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?) + { + DispatchQueue.global(qos: .utility).async { + let formData = MultipartFormData() + multipartFormData(formData) + + var tempFileURL: URL? + + do { + var urlRequestWithContentType = try urlRequest.asURLRequest() + urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type") + + let isBackgroundSession = self.session.configuration.identifier != nil + + if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession { + let data = try formData.encode() + + let encodingResult = MultipartFormDataEncodingResult.success( + request: self.upload(data, with: urlRequestWithContentType), + streamingFromDisk: false, + streamFileURL: nil + ) + + DispatchQueue.main.async { encodingCompletion?(encodingResult) } + } else { + let fileManager = FileManager.default + let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory()) + let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data") + let fileName = UUID().uuidString + let fileURL = directoryURL.appendingPathComponent(fileName) + + tempFileURL = fileURL + + var directoryError: Error? + + // Create directory inside serial queue to ensure two threads don't do this in parallel + self.queue.sync { + do { + try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil) + } catch { + directoryError = error + } + } + + if let directoryError = directoryError { throw directoryError } + + try formData.writeEncodedData(to: fileURL) + + let upload = self.upload(fileURL, with: urlRequestWithContentType) + + // Cleanup the temp file once the upload is complete + upload.delegate.queue.addOperation { + do { + try FileManager.default.removeItem(at: fileURL) + } catch { + // No-op + } + } + + DispatchQueue.main.async { + let encodingResult = MultipartFormDataEncodingResult.success( + request: upload, + streamingFromDisk: true, + streamFileURL: fileURL + ) + + encodingCompletion?(encodingResult) + } + } + } catch { + // Cleanup the temp file in the event that the multipart form data encoding failed + if let tempFileURL = tempFileURL { + do { + try FileManager.default.removeItem(at: tempFileURL) + } catch { + // No-op + } + } + + DispatchQueue.main.async { encodingCompletion?(.failure(error)) } + } + } + } + + // MARK: Private - Upload Implementation + + private func upload(_ uploadable: UploadRequest.Uploadable) -> UploadRequest { + do { + let task = try uploadable.task(session: session, adapter: adapter, queue: queue) + let upload = UploadRequest(session: session, requestTask: .upload(uploadable, task)) + + if case let .stream(inputStream, _) = uploadable { + upload.delegate.taskNeedNewBodyStream = { _, _ in inputStream } + } + + delegate[task] = upload + + if startRequestsImmediately { upload.resume() } + + return upload + } catch { + return upload(uploadable, failedWith: error) + } + } + + private func upload(_ uploadable: UploadRequest.Uploadable?, failedWith error: Error) -> UploadRequest { + var uploadTask: Request.RequestTask = .upload(nil, nil) + + if let uploadable = uploadable { + uploadTask = .upload(uploadable, nil) + } + + let underlyingError = error.underlyingAdaptError ?? error + let upload = UploadRequest(session: session, requestTask: uploadTask, error: underlyingError) + + if let retrier = retrier, error is AdaptError { + allowRetrier(retrier, toRetry: upload, with: underlyingError) + } else { + if startRequestsImmediately { upload.resume() } + } + + return upload + } + +#if !os(watchOS) + + // MARK: - Stream Request + + // MARK: Hostname and Port + + /// Creates a `StreamRequest` for bidirectional streaming using the `hostname` and `port`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter hostName: The hostname of the server to connect to. + /// - parameter port: The port of the server to connect to. + /// + /// - returns: The created `StreamRequest`. + @discardableResult + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open func stream(withHostName hostName: String, port: Int) -> StreamRequest { + return stream(.stream(hostName: hostName, port: port)) + } + + // MARK: NetService + + /// Creates a `StreamRequest` for bidirectional streaming using the `netService`. + /// + /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned. + /// + /// - parameter netService: The net service used to identify the endpoint. + /// + /// - returns: The created `StreamRequest`. + @discardableResult + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + open func stream(with netService: NetService) -> StreamRequest { + return stream(.netService(netService)) + } + + // MARK: Private - Stream Implementation + + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + private func stream(_ streamable: StreamRequest.Streamable) -> StreamRequest { + do { + let task = try streamable.task(session: session, adapter: adapter, queue: queue) + let request = StreamRequest(session: session, requestTask: .stream(streamable, task)) + + delegate[task] = request + + if startRequestsImmediately { request.resume() } + + return request + } catch { + return stream(failedWith: error) + } + } + + @available(iOS 9.0, macOS 10.11, tvOS 9.0, *) + private func stream(failedWith error: Error) -> StreamRequest { + let stream = StreamRequest(session: session, requestTask: .stream(nil, nil), error: error) + if startRequestsImmediately { stream.resume() } + return stream + } + +#endif + + // MARK: - Internal - Retry Request + + func retry(_ request: Request) -> Bool { + guard let originalTask = request.originalTask else { return false } + + do { + let task = try originalTask.task(session: session, adapter: adapter, queue: queue) + + if let originalTask = request.task { + delegate[originalTask] = nil // removes the old request to avoid endless growth + } + + request.delegate.task = task // resets all task delegate data + + request.retryCount += 1 + request.startTime = CFAbsoluteTimeGetCurrent() + request.endTime = nil + + task.resume() + + return true + } catch { + request.delegate.error = error.underlyingAdaptError ?? error + return false + } + } + + private func allowRetrier(_ retrier: RequestRetrier, toRetry request: Request, with error: Error) { + DispatchQueue.utility.async { [weak self] in + guard let strongSelf = self else { return } + + retrier.should(strongSelf, retry: request, with: error) { shouldRetry, timeDelay in + guard let strongSelf = self else { return } + + guard shouldRetry else { + if strongSelf.startRequestsImmediately { request.resume() } + return + } + + DispatchQueue.utility.after(timeDelay) { + guard let strongSelf = self else { return } + + let retrySucceeded = strongSelf.retry(request) + + if retrySucceeded, let task = request.task { + strongSelf.delegate[task] = request + } else { + if strongSelf.startRequestsImmediately { request.resume() } + } + } + } + } + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/TaskDelegate.swift b/SynchronyFinancial/Pods/Alamofire/Source/TaskDelegate.swift new file mode 100644 index 0000000..8e19888 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/TaskDelegate.swift @@ -0,0 +1,466 @@ +// +// TaskDelegate.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// The task delegate is responsible for handling all delegate callbacks for the underlying task as well as +/// executing all operations attached to the serial operation queue upon task completion. +open class TaskDelegate: NSObject { + + // MARK: Properties + + /// The serial operation queue used to execute all operations after the task completes. + public let queue: OperationQueue + + /// The data returned by the server. + public var data: Data? { return nil } + + /// The error generated throughout the lifecyle of the task. + public var error: Error? + + var task: URLSessionTask? { + set { + taskLock.lock(); defer { taskLock.unlock() } + _task = newValue + } + get { + taskLock.lock(); defer { taskLock.unlock() } + return _task + } + } + + var initialResponseTime: CFAbsoluteTime? + var credential: URLCredential? + var metrics: AnyObject? // URLSessionTaskMetrics + + private var _task: URLSessionTask? { + didSet { reset() } + } + + private let taskLock = NSLock() + + // MARK: Lifecycle + + init(task: URLSessionTask?) { + _task = task + + self.queue = { + let operationQueue = OperationQueue() + + operationQueue.maxConcurrentOperationCount = 1 + operationQueue.isSuspended = true + operationQueue.qualityOfService = .utility + + return operationQueue + }() + } + + func reset() { + error = nil + initialResponseTime = nil + } + + // MARK: URLSessionTaskDelegate + + var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)? + var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? + var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)? + var taskDidCompleteWithError: ((URLSession, URLSessionTask, Error?) -> Void)? + + @objc(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:) + func urlSession( + _ session: URLSession, + task: URLSessionTask, + willPerformHTTPRedirection response: HTTPURLResponse, + newRequest request: URLRequest, + completionHandler: @escaping (URLRequest?) -> Void) + { + var redirectRequest: URLRequest? = request + + if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection { + redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request) + } + + completionHandler(redirectRequest) + } + + @objc(URLSession:task:didReceiveChallenge:completionHandler:) + func urlSession( + _ session: URLSession, + task: URLSessionTask, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + { + var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling + var credential: URLCredential? + + if let taskDidReceiveChallenge = taskDidReceiveChallenge { + (disposition, credential) = taskDidReceiveChallenge(session, task, challenge) + } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { + let host = challenge.protectionSpace.host + + if + let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host), + let serverTrust = challenge.protectionSpace.serverTrust + { + if serverTrustPolicy.evaluate(serverTrust, forHost: host) { + disposition = .useCredential + credential = URLCredential(trust: serverTrust) + } else { + disposition = .cancelAuthenticationChallenge + } + } + } else { + if challenge.previousFailureCount > 0 { + disposition = .rejectProtectionSpace + } else { + credential = self.credential ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace) + + if credential != nil { + disposition = .useCredential + } + } + } + + completionHandler(disposition, credential) + } + + @objc(URLSession:task:needNewBodyStream:) + func urlSession( + _ session: URLSession, + task: URLSessionTask, + needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) + { + var bodyStream: InputStream? + + if let taskNeedNewBodyStream = taskNeedNewBodyStream { + bodyStream = taskNeedNewBodyStream(session, task) + } + + completionHandler(bodyStream) + } + + @objc(URLSession:task:didCompleteWithError:) + func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { + if let taskDidCompleteWithError = taskDidCompleteWithError { + taskDidCompleteWithError(session, task, error) + } else { + if let error = error { + if self.error == nil { self.error = error } + + if + let downloadDelegate = self as? DownloadTaskDelegate, + let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data + { + downloadDelegate.resumeData = resumeData + } + } + + queue.isSuspended = false + } + } +} + +// MARK: - + +class DataTaskDelegate: TaskDelegate, URLSessionDataDelegate { + + // MARK: Properties + + var dataTask: URLSessionDataTask { return task as! URLSessionDataTask } + + override var data: Data? { + if dataStream != nil { + return nil + } else { + return mutableData + } + } + + var progress: Progress + var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? + + var dataStream: ((_ data: Data) -> Void)? + + private var totalBytesReceived: Int64 = 0 + private var mutableData: Data + + private var expectedContentLength: Int64? + + // MARK: Lifecycle + + override init(task: URLSessionTask?) { + mutableData = Data() + progress = Progress(totalUnitCount: 0) + + super.init(task: task) + } + + override func reset() { + super.reset() + + progress = Progress(totalUnitCount: 0) + totalBytesReceived = 0 + mutableData = Data() + expectedContentLength = nil + } + + // MARK: URLSessionDataDelegate + + var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)? + var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)? + var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)? + var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)? + + func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didReceive response: URLResponse, + completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) + { + var disposition: URLSession.ResponseDisposition = .allow + + expectedContentLength = response.expectedContentLength + + if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse { + disposition = dataTaskDidReceiveResponse(session, dataTask, response) + } + + completionHandler(disposition) + } + + func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + didBecome downloadTask: URLSessionDownloadTask) + { + dataTaskDidBecomeDownloadTask?(session, dataTask, downloadTask) + } + + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { + if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } + + if let dataTaskDidReceiveData = dataTaskDidReceiveData { + dataTaskDidReceiveData(session, dataTask, data) + } else { + if let dataStream = dataStream { + dataStream(data) + } else { + mutableData.append(data) + } + + let bytesReceived = Int64(data.count) + totalBytesReceived += bytesReceived + let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown + + progress.totalUnitCount = totalBytesExpected + progress.completedUnitCount = totalBytesReceived + + if let progressHandler = progressHandler { + progressHandler.queue.async { progressHandler.closure(self.progress) } + } + } + } + + func urlSession( + _ session: URLSession, + dataTask: URLSessionDataTask, + willCacheResponse proposedResponse: CachedURLResponse, + completionHandler: @escaping (CachedURLResponse?) -> Void) + { + var cachedResponse: CachedURLResponse? = proposedResponse + + if let dataTaskWillCacheResponse = dataTaskWillCacheResponse { + cachedResponse = dataTaskWillCacheResponse(session, dataTask, proposedResponse) + } + + completionHandler(cachedResponse) + } +} + +// MARK: - + +class DownloadTaskDelegate: TaskDelegate, URLSessionDownloadDelegate { + + // MARK: Properties + + var downloadTask: URLSessionDownloadTask { return task as! URLSessionDownloadTask } + + var progress: Progress + var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? + + var resumeData: Data? + override var data: Data? { return resumeData } + + var destination: DownloadRequest.DownloadFileDestination? + + var temporaryURL: URL? + var destinationURL: URL? + + var fileURL: URL? { return destination != nil ? destinationURL : temporaryURL } + + // MARK: Lifecycle + + override init(task: URLSessionTask?) { + progress = Progress(totalUnitCount: 0) + super.init(task: task) + } + + override func reset() { + super.reset() + + progress = Progress(totalUnitCount: 0) + resumeData = nil + } + + // MARK: URLSessionDownloadDelegate + + var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> URL)? + var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)? + var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)? + + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didFinishDownloadingTo location: URL) + { + temporaryURL = location + + guard + let destination = destination, + let response = downloadTask.response as? HTTPURLResponse + else { return } + + let result = destination(location, response) + let destinationURL = result.destinationURL + let options = result.options + + self.destinationURL = destinationURL + + do { + if options.contains(.removePreviousFile), FileManager.default.fileExists(atPath: destinationURL.path) { + try FileManager.default.removeItem(at: destinationURL) + } + + if options.contains(.createIntermediateDirectories) { + let directory = destinationURL.deletingLastPathComponent() + try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) + } + + try FileManager.default.moveItem(at: location, to: destinationURL) + } catch { + self.error = error + } + } + + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didWriteData bytesWritten: Int64, + totalBytesWritten: Int64, + totalBytesExpectedToWrite: Int64) + { + if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } + + if let downloadTaskDidWriteData = downloadTaskDidWriteData { + downloadTaskDidWriteData( + session, + downloadTask, + bytesWritten, + totalBytesWritten, + totalBytesExpectedToWrite + ) + } else { + progress.totalUnitCount = totalBytesExpectedToWrite + progress.completedUnitCount = totalBytesWritten + + if let progressHandler = progressHandler { + progressHandler.queue.async { progressHandler.closure(self.progress) } + } + } + } + + func urlSession( + _ session: URLSession, + downloadTask: URLSessionDownloadTask, + didResumeAtOffset fileOffset: Int64, + expectedTotalBytes: Int64) + { + if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { + downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) + } else { + progress.totalUnitCount = expectedTotalBytes + progress.completedUnitCount = fileOffset + } + } +} + +// MARK: - + +class UploadTaskDelegate: DataTaskDelegate { + + // MARK: Properties + + var uploadTask: URLSessionUploadTask { return task as! URLSessionUploadTask } + + var uploadProgress: Progress + var uploadProgressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? + + // MARK: Lifecycle + + override init(task: URLSessionTask?) { + uploadProgress = Progress(totalUnitCount: 0) + super.init(task: task) + } + + override func reset() { + super.reset() + uploadProgress = Progress(totalUnitCount: 0) + } + + // MARK: URLSessionTaskDelegate + + var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)? + + func URLSession( + _ session: URLSession, + task: URLSessionTask, + didSendBodyData bytesSent: Int64, + totalBytesSent: Int64, + totalBytesExpectedToSend: Int64) + { + if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } + + if let taskDidSendBodyData = taskDidSendBodyData { + taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) + } else { + uploadProgress.totalUnitCount = totalBytesExpectedToSend + uploadProgress.completedUnitCount = totalBytesSent + + if let uploadProgressHandler = uploadProgressHandler { + uploadProgressHandler.queue.async { uploadProgressHandler.closure(self.uploadProgress) } + } + } + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Timeline.swift b/SynchronyFinancial/Pods/Alamofire/Source/Timeline.swift new file mode 100644 index 0000000..181c988 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Timeline.swift @@ -0,0 +1,136 @@ +// +// Timeline.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +/// Responsible for computing the timing metrics for the complete lifecycle of a `Request`. +public struct Timeline { + /// The time the request was initialized. + public let requestStartTime: CFAbsoluteTime + + /// The time the first bytes were received from or sent to the server. + public let initialResponseTime: CFAbsoluteTime + + /// The time when the request was completed. + public let requestCompletedTime: CFAbsoluteTime + + /// The time when the response serialization was completed. + public let serializationCompletedTime: CFAbsoluteTime + + /// The time interval in seconds from the time the request started to the initial response from the server. + public let latency: TimeInterval + + /// The time interval in seconds from the time the request started to the time the request completed. + public let requestDuration: TimeInterval + + /// The time interval in seconds from the time the request completed to the time response serialization completed. + public let serializationDuration: TimeInterval + + /// The time interval in seconds from the time the request started to the time response serialization completed. + public let totalDuration: TimeInterval + + /// Creates a new `Timeline` instance with the specified request times. + /// + /// - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`. + /// - parameter initialResponseTime: The time the first bytes were received from or sent to the server. + /// Defaults to `0.0`. + /// - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`. + /// - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults + /// to `0.0`. + /// + /// - returns: The new `Timeline` instance. + public init( + requestStartTime: CFAbsoluteTime = 0.0, + initialResponseTime: CFAbsoluteTime = 0.0, + requestCompletedTime: CFAbsoluteTime = 0.0, + serializationCompletedTime: CFAbsoluteTime = 0.0) + { + self.requestStartTime = requestStartTime + self.initialResponseTime = initialResponseTime + self.requestCompletedTime = requestCompletedTime + self.serializationCompletedTime = serializationCompletedTime + + self.latency = initialResponseTime - requestStartTime + self.requestDuration = requestCompletedTime - requestStartTime + self.serializationDuration = serializationCompletedTime - requestCompletedTime + self.totalDuration = serializationCompletedTime - requestStartTime + } +} + +// MARK: - CustomStringConvertible + +extension Timeline: CustomStringConvertible { + /// The textual representation used when written to an output stream, which includes the latency, the request + /// duration and the total duration. + public var description: String { + let latency = String(format: "%.3f", self.latency) + let requestDuration = String(format: "%.3f", self.requestDuration) + let serializationDuration = String(format: "%.3f", self.serializationDuration) + let totalDuration = String(format: "%.3f", self.totalDuration) + + // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is + // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. + let timings = [ + "\"Latency\": " + latency + " secs", + "\"Request Duration\": " + requestDuration + " secs", + "\"Serialization Duration\": " + serializationDuration + " secs", + "\"Total Duration\": " + totalDuration + " secs" + ] + + return "Timeline: { " + timings.joined(separator: ", ") + " }" + } +} + +// MARK: - CustomDebugStringConvertible + +extension Timeline: CustomDebugStringConvertible { + /// The textual representation used when written to an output stream, which includes the request start time, the + /// initial response time, the request completed time, the serialization completed time, the latency, the request + /// duration and the total duration. + public var debugDescription: String { + let requestStartTime = String(format: "%.3f", self.requestStartTime) + let initialResponseTime = String(format: "%.3f", self.initialResponseTime) + let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime) + let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime) + let latency = String(format: "%.3f", self.latency) + let requestDuration = String(format: "%.3f", self.requestDuration) + let serializationDuration = String(format: "%.3f", self.serializationDuration) + let totalDuration = String(format: "%.3f", self.totalDuration) + + // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is + // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. + let timings = [ + "\"Request Start Time\": " + requestStartTime, + "\"Initial Response Time\": " + initialResponseTime, + "\"Request Completed Time\": " + requestCompletedTime, + "\"Serialization Completed Time\": " + serializationCompletedTime, + "\"Latency\": " + latency + " secs", + "\"Request Duration\": " + requestDuration + " secs", + "\"Serialization Duration\": " + serializationDuration + " secs", + "\"Total Duration\": " + totalDuration + " secs" + ] + + return "Timeline: { " + timings.joined(separator: ", ") + " }" + } +} diff --git a/SynchronyFinancial/Pods/Alamofire/Source/Validation.swift b/SynchronyFinancial/Pods/Alamofire/Source/Validation.swift new file mode 100644 index 0000000..ec2c5c3 --- /dev/null +++ b/SynchronyFinancial/Pods/Alamofire/Source/Validation.swift @@ -0,0 +1,315 @@ +// +// Validation.swift +// +// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) +// +// 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 Foundation + +extension Request { + + // MARK: Helper Types + + fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason + + /// Used to represent whether validation was successful or encountered an error resulting in a failure. + /// + /// - success: The validation was successful. + /// - failure: The validation failed encountering the provided error. + public enum ValidationResult { + case success + case failure(Error) + } + + fileprivate struct MIMEType { + let type: String + let subtype: String + + var isWildcard: Bool { return type == "*" && subtype == "*" } + + init?(_ string: String) { + let components: [String] = { + let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines) + + #if swift(>=3.2) + let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)] + #else + let split = stripped.substring(to: stripped.range(of: ";")?.lowerBound ?? stripped.endIndex) + #endif + + return split.components(separatedBy: "/") + }() + + if let type = components.first, let subtype = components.last { + self.type = type + self.subtype = subtype + } else { + return nil + } + } + + func matches(_ mime: MIMEType) -> Bool { + switch (type, subtype) { + case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"): + return true + default: + return false + } + } + } + + // MARK: Properties + + fileprivate var acceptableStatusCodes: [Int] { return Array(200..<300) } + + fileprivate var acceptableContentTypes: [String] { + if let accept = request?.value(forHTTPHeaderField: "Accept") { + return accept.components(separatedBy: ",") + } + + return ["*/*"] + } + + // MARK: Status Code + + fileprivate func validate( + statusCode acceptableStatusCodes: S, + response: HTTPURLResponse) + -> ValidationResult + where S.Iterator.Element == Int + { + if acceptableStatusCodes.contains(response.statusCode) { + return .success + } else { + let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode) + return .failure(AFError.responseValidationFailed(reason: reason)) + } + } + + // MARK: Content Type + + fileprivate func validate( + contentType acceptableContentTypes: S, + response: HTTPURLResponse, + data: Data?) + -> ValidationResult + where S.Iterator.Element == String + { + guard let data = data, data.count > 0 else { return .success } + + guard + let responseContentType = response.mimeType, + let responseMIMEType = MIMEType(responseContentType) + else { + for contentType in acceptableContentTypes { + if let mimeType = MIMEType(contentType), mimeType.isWildcard { + return .success + } + } + + let error: AFError = { + let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes)) + return AFError.responseValidationFailed(reason: reason) + }() + + return .failure(error) + } + + for contentType in acceptableContentTypes { + if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) { + return .success + } + } + + let error: AFError = { + let reason: ErrorReason = .unacceptableContentType( + acceptableContentTypes: Array(acceptableContentTypes), + responseContentType: responseContentType + ) + + return AFError.responseValidationFailed(reason: reason) + }() + + return .failure(error) + } +} + +// MARK: - + +extension DataRequest { + /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the + /// request was valid. + public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult + + /// Validates the request, using the specified closure. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter validation: A closure to validate the request. + /// + /// - returns: The request. + @discardableResult + public func validate(_ validation: @escaping Validation) -> Self { + let validationExecution: () -> Void = { [unowned self] in + if + let response = self.response, + self.delegate.error == nil, + case let .failure(error) = validation(self.request, response, self.delegate.data) + { + self.delegate.error = error + } + } + + validations.append(validationExecution) + + return self + } + + /// Validates that the response has a status code in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter range: The range of acceptable status codes. + /// + /// - returns: The request. + @discardableResult + public func validate(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int { + return validate { [unowned self] _, response, _ in + return self.validate(statusCode: acceptableStatusCodes, response: response) + } + } + + /// Validates that the response has a content type in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. + /// + /// - returns: The request. + @discardableResult + public func validate(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String { + return validate { [unowned self] _, response, data in + return self.validate(contentType: acceptableContentTypes, response: response, data: data) + } + } + + /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content + /// type matches any specified in the Accept HTTP header field. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - returns: The request. + @discardableResult + public func validate() -> Self { + return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes) + } +} + +// MARK: - + +extension DownloadRequest { + /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a + /// destination URL, and returns whether the request was valid. + public typealias Validation = ( + _ request: URLRequest?, + _ response: HTTPURLResponse, + _ temporaryURL: URL?, + _ destinationURL: URL?) + -> ValidationResult + + /// Validates the request, using the specified closure. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter validation: A closure to validate the request. + /// + /// - returns: The request. + @discardableResult + public func validate(_ validation: @escaping Validation) -> Self { + let validationExecution: () -> Void = { [unowned self] in + let request = self.request + let temporaryURL = self.downloadDelegate.temporaryURL + let destinationURL = self.downloadDelegate.destinationURL + + if + let response = self.response, + self.delegate.error == nil, + case let .failure(error) = validation(request, response, temporaryURL, destinationURL) + { + self.delegate.error = error + } + } + + validations.append(validationExecution) + + return self + } + + /// Validates that the response has a status code in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter range: The range of acceptable status codes. + /// + /// - returns: The request. + @discardableResult + public func validate(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int { + return validate { [unowned self] _, response, _, _ in + return self.validate(statusCode: acceptableStatusCodes, response: response) + } + } + + /// Validates that the response has a content type in the specified sequence. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. + /// + /// - returns: The request. + @discardableResult + public func validate(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String { + return validate { [unowned self] _, response, _, _ in + let fileURL = self.downloadDelegate.fileURL + + guard let validFileURL = fileURL else { + return .failure(AFError.responseValidationFailed(reason: .dataFileNil)) + } + + do { + let data = try Data(contentsOf: validFileURL) + return self.validate(contentType: acceptableContentTypes, response: response, data: data) + } catch { + return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL))) + } + } + } + + /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content + /// type matches any specified in the Accept HTTP header field. + /// + /// If validation fails, subsequent calls to response handlers will have an associated error. + /// + /// - returns: The request. + @discardableResult + public func validate() -> Self { + return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes) + } +} diff --git a/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-iOS-umbrella.h b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-iOS-umbrella.h new file mode 100644 index 0000000..00014e3 --- /dev/null +++ b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-iOS-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 AlamofireVersionNumber; +FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; + diff --git a/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-iOS.modulemap b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-iOS.modulemap new file mode 100644 index 0000000..d0f2374 --- /dev/null +++ b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-iOS.modulemap @@ -0,0 +1,7 @@ +module Alamofire { + umbrella header "Alamofire-iOS-umbrella.h" + exclude header "Alamofire-watchOS-umbrella.h" + + export * + module * { export * } +} diff --git a/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-watchOS-umbrella.h b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-watchOS-umbrella.h new file mode 100644 index 0000000..0d8e6bd --- /dev/null +++ b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-watchOS-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 AlamofireVersionNumber; +FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; + diff --git a/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-watchOS.modulemap b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-watchOS.modulemap new file mode 100644 index 0000000..ce220b5 --- /dev/null +++ b/SynchronyFinancial/Pods/Headers/Public/Alamofire/Alamofire-watchOS.modulemap @@ -0,0 +1,7 @@ +module Alamofire { + umbrella header "Alamofire-watchOS-umbrella.h" + exclude header "Alamofire-iOS-umbrella.h" + + export * + module * { export * } +} diff --git a/SynchronyFinancial/Pods/Manifest.lock b/SynchronyFinancial/Pods/Manifest.lock index 92ee303..1f05592 100644 --- a/SynchronyFinancial/Pods/Manifest.lock +++ b/SynchronyFinancial/Pods/Manifest.lock @@ -1,16 +1,20 @@ PODS: + - Alamofire (4.7.3) - SwiftLint (0.27.0) DEPENDENCIES: + - Alamofire - SwiftLint SPEC REPOS: https://github.com/cocoapods/specs.git: + - Alamofire - SwiftLint SPEC CHECKSUMS: + Alamofire: c7287b6e5d7da964a70935e5db17046b7fde6568 SwiftLint: 3207c1faa2240bf8973b191820a116113cd11073 -PODFILE CHECKSUM: 4677f0f790934708825f5fcde561667ebefd2df5 +PODFILE CHECKSUM: 8390a2d9691b418a9cdf2f8053ba0a852a522b37 COCOAPODS: 1.5.3 diff --git a/SynchronyFinancial/Pods/Pods.xcodeproj/project.pbxproj b/SynchronyFinancial/Pods/Pods.xcodeproj/project.pbxproj index eb075d3..8eb8a6c 100644 --- a/SynchronyFinancial/Pods/Pods.xcodeproj/project.pbxproj +++ b/SynchronyFinancial/Pods/Pods.xcodeproj/project.pbxproj @@ -7,55 +7,169 @@ objects = { /* Begin PBXBuildFile section */ - 40786BCC70FAE2E0979F6BE1509C1D67 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 73414FA9DAEB014677753FA4EC70919F /* Pods-SynchronyFinancial WatchKit Extension-dummy.m */; }; - 9EE883E312A828174A57FC699BEE740B /* Pods-SynchronyFinancial WatchKit App-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F5DD302624CB5C74B7F2F41755B5F1E /* Pods-SynchronyFinancial WatchKit App-dummy.m */; }; - C9ED209725BA93A2E09CE9745A7F124A /* Pods-SynchronyFinancial-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 223A928E0610C878C2936F0B3F67F128 /* Pods-SynchronyFinancial-dummy.m */; }; + 06AD8F515AA607C8CB47865D93E97E16 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 37BDDE6101FAF9052E04078C570E0CB5 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m */; }; + 16C7AC67BDFE60A674BC8A4F508DD60C /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F82C8BB9CF77CC85718EB72F1E9FB8 /* Result.swift */; }; + 17F5A3C3C1FF68BF98C5C67214A10DA8 /* SessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8DDCA62346A9286701819B9F049E579 /* SessionManager.swift */; }; + 1A0FF2D7AB93FEAEABFB337A470FBCF4 /* Pods-SynchronyFinancial-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9555A6B2965DFDC55D0387648293A42F /* Pods-SynchronyFinancial-dummy.m */; }; + 1BDC0921F64F29554B83E7B70395CB11 /* Alamofire-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C17C972C596660048C58467D76C70664 /* Alamofire-iOS-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1D45D8BCE32A05EDCBB89D2C296A46E1 /* Pods-SynchronyFinancial WatchKit Extension-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 22D3304892D7984CB8C48B7D236AC3F6 /* Pods-SynchronyFinancial WatchKit Extension-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 211C56E073E89711CFC0B564D6DE3DBC /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEACB5D3C3E83582595EE3DA3B42CFD3 /* SessionDelegate.swift */; }; + 386CECFA45DFF6191BECE87AF9F3E3DF /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94C872345A1E81337AC8C19DB3D7DF1 /* NetworkReachabilityManager.swift */; }; + 3C599707E21CF41062AB104EFA961B29 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC8E1DC5E17A25E87566D8D4BB34A5CA /* AFError.swift */; }; + 42788A9753A4D04D53BEA70CBB7DF705 /* Pods-SynchronyFinancial WatchKit App-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 848A32D3ABE543896C0E61DC0DB2DC48 /* Pods-SynchronyFinancial WatchKit App-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 433CB78DFCA4AEEB4799FE22E448E783 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3A23ED84B2A322445815BE53FCDC7A /* MultipartFormData.swift */; }; + 4A90EE80279B2A3B26B176543654C368 /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890C65E53958E5AE67698437CA76F9E5 /* DispatchQueue+Alamofire.swift */; }; + 4F434A210C06FA4F4194A3CDA5C39F0C /* Alamofire-watchOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 23E68A43BE6AEE7C774A6C2F81FA32E1 /* Alamofire-watchOS-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5248A82654243159E7E3BF56537E9DF3 /* AFError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC8E1DC5E17A25E87566D8D4BB34A5CA /* AFError.swift */; }; + 60035FFA16C07A85E68CE346939F2B6F /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F926E34C9F3384D6C4EFCCA1FA84B5D3 /* ServerTrustPolicy.swift */; }; + 60F5CDD4E36FECB47E136B191AAC39C7 /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D35191BEC74246D30F8BCCC900A65C44 /* ParameterEncoding.swift */; }; + 702E11E33684ADEF848F6747405051BA /* NetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94C872345A1E81337AC8C19DB3D7DF1 /* NetworkReachabilityManager.swift */; }; + 763240E338AFF56BE6B70F65DC438045 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70416CD1D8FC178C04A02A149C11971 /* Timeline.swift */; }; + 7F3D2A1E85D34B7B1CB3A244C179C700 /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A86C55E839A0051646DA6AB8952C506 /* Validation.swift */; }; + 82EADC7327F5F572A58D410DCF3DE3BF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = A887B9AEFC28E0F81536EC8A5F82DEE4 /* Response.swift */; }; + 8995E81689ED6E5D86A4A549A736ABD5 /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = C098C75CF5A1A0AE043F25CEBE6D3A94 /* ResponseSerialization.swift */; }; + 8EA6A1E73DF672BBBC94B1D9BB685DDD /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 938335C8A86618E6479B72666E8B3472 /* Alamofire.swift */; }; + 922D040FE414B746702500EBA4E0A64C /* TaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E743C86FF4065DCC16BBD3D2317EDB /* TaskDelegate.swift */; }; + 97D1C0EA155278A4C435B89B772CEAFB /* Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 938335C8A86618E6479B72666E8B3472 /* Alamofire.swift */; }; + 98EBB2E00D23DAD35E2E3E1F4920557D /* DispatchQueue+Alamofire.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890C65E53958E5AE67698437CA76F9E5 /* DispatchQueue+Alamofire.swift */; }; + 9A54CB8CA91C572E283699874260036C /* ResponseSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = C098C75CF5A1A0AE043F25CEBE6D3A94 /* ResponseSerialization.swift */; }; + 9EC4FEE90C2B8607BB2B1620A528ACAD /* Alamofire-iOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E3FD293B6881D7FA4F8F099F9D0E8BDC /* Alamofire-iOS-dummy.m */; }; + AD5A8C570F6D58F4DEBD0EC478B34996 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70416CD1D8FC178C04A02A149C11971 /* Timeline.swift */; }; + ADE79C2381EED50B80561A6229B84CA9 /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A86C55E839A0051646DA6AB8952C506 /* Validation.swift */; }; + AFB761B750134903DB4DC8E80595D3EC /* Alamofire-watchOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 726B125FA1325683D7E7A28E2E51F269 /* Alamofire-watchOS-dummy.m */; }; + B51C64A54D1D60EE396D519B0EF7B98C /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF6EAF4EA7DB08F8A58F4B8E0BA1099D /* Request.swift */; }; + BC8B935096B146374B4439F42AFA7421 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F82C8BB9CF77CC85718EB72F1E9FB8 /* Result.swift */; }; + C59F2B590B0C69031ACB9170812B3AF6 /* ParameterEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D35191BEC74246D30F8BCCC900A65C44 /* ParameterEncoding.swift */; }; + CDB9D5D771EC41C24E5FC025CDD2F02D /* Pods-SynchronyFinancial WatchKit App-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CB542604CFB0314507EEC5225EB4B64 /* Pods-SynchronyFinancial WatchKit App-dummy.m */; }; + D40E7525C96B28DEC2E260D9EFD66E67 /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F926E34C9F3384D6C4EFCCA1FA84B5D3 /* ServerTrustPolicy.swift */; }; + DBFFF690F7E108F7C5A3D3D76871D557 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF6EAF4EA7DB08F8A58F4B8E0BA1099D /* Request.swift */; }; + DD2222A99E09A2E7FD6F721A3C32E40F /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB2C4D8119B2B3386DF57724B6FFE42 /* Notifications.swift */; }; + E108694CE400C627D9A28BF8EFCEDC83 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEACB5D3C3E83582595EE3DA3B42CFD3 /* SessionDelegate.swift */; }; + E49DE408E8EA7B65B1AF4DC004F6D099 /* Pods-SynchronyFinancial-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 03E19667BC72E1E238261E24CD564E30 /* Pods-SynchronyFinancial-umbrella.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E6ADB328EEFDD2769CD7B5216F455968 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = A887B9AEFC28E0F81536EC8A5F82DEE4 /* Response.swift */; }; + EF1D70E53200EE4CB2F21890CF75B1D2 /* SessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8DDCA62346A9286701819B9F049E579 /* SessionManager.swift */; }; + F68AF157549FE798EEBCEB19B1FD28B0 /* MultipartFormData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B3A23ED84B2A322445815BE53FCDC7A /* MultipartFormData.swift */; }; + F85151956AE3CFEEAA2B1B626C9FA4FC /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB2C4D8119B2B3386DF57724B6FFE42 /* Notifications.swift */; }; + FC686378DFFBEFB17B00BBD94333B7CC /* TaskDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23E743C86FF4065DCC16BBD3D2317EDB /* TaskDelegate.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 73BA8BAB2DFC05CA43738D9049E43B08 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 449BDE5D9D406B30E8E4E97CD9DF4F01; + remoteInfo = "Alamofire-iOS"; + }; + B2FB7006531883F892E7CA8DE39A304D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = B8E4738C39F45964F0C646DC61C880BB; + remoteInfo = "Alamofire-watchOS"; + }; + E75DF8434FC6AE4EA1080FA7F88FFAE7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = B8E4738C39F45964F0C646DC61C880BB; + remoteInfo = "Alamofire-watchOS"; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ - 0C620C5446A023E3F572797CDF582D02 /* Pods-SynchronyFinancial-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial-resources.sh"; sourceTree = ""; }; - 0EA3ACB934ED5CC20B03ED0284DC7ED6 /* Pods-SynchronyFinancial-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial-frameworks.sh"; sourceTree = ""; }; - 12A852DC2609D33030D800D26DE0E3FF /* Pods-SynchronyFinancial WatchKit Extension-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit Extension-resources.sh"; sourceTree = ""; }; - 1537C7EC3F51C446C8E8D32F9D470930 /* Pods-SynchronyFinancial WatchKit App-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit App-frameworks.sh"; sourceTree = ""; }; - 223A928E0610C878C2936F0B3F67F128 /* Pods-SynchronyFinancial-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SynchronyFinancial-dummy.m"; sourceTree = ""; }; - 3313A253E1368C5838C70D2E4BCF6805 /* Pods-SynchronyFinancial-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SynchronyFinancial-acknowledgements.markdown"; sourceTree = ""; }; - 38B1BBE679F86F1EDCEC91ADF251D892 /* libPods-SynchronyFinancial WatchKit Extension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-SynchronyFinancial WatchKit Extension.a"; path = "libPods-SynchronyFinancial WatchKit Extension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 3D8FBB1F320C4DC436EF5B6981045F78 /* Pods-SynchronyFinancial WatchKit App-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit App-resources.sh"; sourceTree = ""; }; - 457688DD3D6D97D5F9359A9958B638D5 /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist"; sourceTree = ""; }; - 50F7E546853B4F5A1AECB55BD2BE3608 /* Pods-SynchronyFinancial-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SynchronyFinancial-acknowledgements.plist"; sourceTree = ""; }; - 57E684B1EF7582F71059B34345C49933 /* Pods-SynchronyFinancial WatchKit Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit Extension.release.xcconfig"; sourceTree = ""; }; - 63744D3728BF84FDF191D7F7CE4AD656 /* libPods-SynchronyFinancial WatchKit App.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-SynchronyFinancial WatchKit App.a"; path = "libPods-SynchronyFinancial WatchKit App.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 73414FA9DAEB014677753FA4EC70919F /* Pods-SynchronyFinancial WatchKit Extension-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SynchronyFinancial WatchKit Extension-dummy.m"; sourceTree = ""; }; - 7F5DD302624CB5C74B7F2F41755B5F1E /* Pods-SynchronyFinancial WatchKit App-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SynchronyFinancial WatchKit App-dummy.m"; sourceTree = ""; }; - 88C8CC772368957E67DC04939293976C /* libPods-SynchronyFinancial.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-SynchronyFinancial.a"; path = "libPods-SynchronyFinancial.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 03E19667BC72E1E238261E24CD564E30 /* Pods-SynchronyFinancial-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-SynchronyFinancial-umbrella.h"; sourceTree = ""; }; + 0496E630215776378A9F46EB6C1A3DF0 /* libPods-SynchronyFinancial WatchKit App.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-SynchronyFinancial WatchKit App.a"; path = "libPods-SynchronyFinancial WatchKit App.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0BB2C4D8119B2B3386DF57724B6FFE42 /* Notifications.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Notifications.swift; path = Source/Notifications.swift; sourceTree = ""; }; + 1D108A04C250B757FFCA530C141F1214 /* Alamofire-watchOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Alamofire-watchOS.xcconfig"; path = "../Alamofire-watchOS/Alamofire-watchOS.xcconfig"; sourceTree = ""; }; + 1DFA543FE9FB2C8ADCCAC70C1F268481 /* libAlamofire-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libAlamofire-iOS.a"; path = "libAlamofire-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F31328046BB381D71AAFDF15525D78B /* Pods-SynchronyFinancial WatchKit Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit Extension.release.xcconfig"; sourceTree = ""; }; + 22D3304892D7984CB8C48B7D236AC3F6 /* Pods-SynchronyFinancial WatchKit Extension-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-SynchronyFinancial WatchKit Extension-umbrella.h"; sourceTree = ""; }; + 23E68A43BE6AEE7C774A6C2F81FA32E1 /* Alamofire-watchOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Alamofire-watchOS-umbrella.h"; path = "../../Headers/Public/Alamofire/Alamofire-watchOS-umbrella.h"; sourceTree = ""; }; + 23E743C86FF4065DCC16BBD3D2317EDB /* TaskDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TaskDelegate.swift; path = Source/TaskDelegate.swift; sourceTree = ""; }; + 2B3A23ED84B2A322445815BE53FCDC7A /* MultipartFormData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MultipartFormData.swift; path = Source/MultipartFormData.swift; sourceTree = ""; }; + 2B4527DE8A4A826FD88BE08AFFEBEEA8 /* Pods-SynchronyFinancial WatchKit App-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit App-resources.sh"; sourceTree = ""; }; + 2B6E27EFC7E2A6157C6AD726AD1B26E0 /* Pods-SynchronyFinancial WatchKit Extension-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit Extension-frameworks.sh"; sourceTree = ""; }; + 2CEB3B037F3EDCFE35FE79D27D7801FF /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown"; sourceTree = ""; }; + 37BDDE6101FAF9052E04078C570E0CB5 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SynchronyFinancial WatchKit Extension-dummy.m"; sourceTree = ""; }; + 39388D231E4A59E61553D8130BB544EB /* Alamofire-watchOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Alamofire-watchOS-prefix.pch"; path = "../Alamofire-watchOS/Alamofire-watchOS-prefix.pch"; sourceTree = ""; }; + 3A86C55E839A0051646DA6AB8952C506 /* Validation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Validation.swift; path = Source/Validation.swift; sourceTree = ""; }; + 4259FFBBEFB620F748F6C7933ECE173A /* libPods-SynchronyFinancial WatchKit Extension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-SynchronyFinancial WatchKit Extension.a"; path = "libPods-SynchronyFinancial WatchKit Extension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 487E55B2BBEFDD99BE20143A1E7DF181 /* Pods-SynchronyFinancial WatchKit Extension-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit Extension-resources.sh"; sourceTree = ""; }; + 4B98B3A9F78869E2C0EC19625A2BE917 /* Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig"; sourceTree = ""; }; + 4CB542604CFB0314507EEC5225EB4B64 /* Pods-SynchronyFinancial WatchKit App-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SynchronyFinancial WatchKit App-dummy.m"; sourceTree = ""; }; + 4EF87963D687D12C78C9CAFC3E389987 /* Pods-SynchronyFinancial-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial-frameworks.sh"; sourceTree = ""; }; + 5487630E77717246F089B8C039034743 /* Pods-SynchronyFinancial WatchKit App-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit App-frameworks.sh"; sourceTree = ""; }; + 5A843197C4CAEDE101D9A76A0A416E9D /* Pods-SynchronyFinancial.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-SynchronyFinancial.modulemap"; sourceTree = ""; }; + 668280BA4A5081F50698A173BCC0E7FE /* Pods-SynchronyFinancial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial.release.xcconfig"; sourceTree = ""; }; + 726B125FA1325683D7E7A28E2E51F269 /* Alamofire-watchOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "Alamofire-watchOS-dummy.m"; path = "../Alamofire-watchOS/Alamofire-watchOS-dummy.m"; sourceTree = ""; }; + 72E4CE044ED07D65A3422CA2D0E23AA8 /* Pods-SynchronyFinancial WatchKit App.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-SynchronyFinancial WatchKit App.modulemap"; sourceTree = ""; }; + 797029C829F77B6F8D46FD6DBD1B1B38 /* Pods-SynchronyFinancial-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial-resources.sh"; sourceTree = ""; }; + 79B982FACBEE749DC74DFB3A916A2A56 /* Alamofire-watchOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; name = "Alamofire-watchOS.modulemap"; path = "../../Headers/Public/Alamofire/Alamofire-watchOS.modulemap"; sourceTree = ""; }; + 848A32D3ABE543896C0E61DC0DB2DC48 /* Pods-SynchronyFinancial WatchKit App-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-SynchronyFinancial WatchKit App-umbrella.h"; sourceTree = ""; }; + 890C65E53958E5AE67698437CA76F9E5 /* DispatchQueue+Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DispatchQueue+Alamofire.swift"; path = "Source/DispatchQueue+Alamofire.swift"; sourceTree = ""; }; + 938335C8A86618E6479B72666E8B3472 /* Alamofire.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Alamofire.swift; path = Source/Alamofire.swift; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - A7709832E45752BA1DB6E6DD56492533 /* Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig"; sourceTree = ""; }; - A97A3561E549200D718457DE1DA30E70 /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown"; sourceTree = ""; }; - A9B5D092ECDBAB4F9C04EF1C1102C7FD /* Pods-SynchronyFinancial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial.debug.xcconfig"; sourceTree = ""; }; - AE59890BB0AF9ABE93999F3BA2C48220 /* Pods-SynchronyFinancial WatchKit Extension-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SynchronyFinancial WatchKit Extension-frameworks.sh"; sourceTree = ""; }; - B821AEADF995C7AF278DB3565B4510D0 /* Pods-SynchronyFinancial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial.release.xcconfig"; sourceTree = ""; }; - CAD575327346729A8CA1067BF0E8940B /* Pods-SynchronyFinancial WatchKit App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit App.debug.xcconfig"; sourceTree = ""; }; - D2712C00382A53A331ECBA6531436563 /* Pods-SynchronyFinancial WatchKit App-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SynchronyFinancial WatchKit App-acknowledgements.plist"; sourceTree = ""; }; - E88AB63B9BC4A9BC88EBEEBA4E823161 /* Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown"; sourceTree = ""; }; - FA232DDB2CBE07129517FCB5EC00D516 /* Pods-SynchronyFinancial WatchKit App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit App.release.xcconfig"; sourceTree = ""; }; + 94C7891EDD57DC7CE6A69164AAAB6BE9 /* Alamofire-iOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; name = "Alamofire-iOS.modulemap"; path = "../../Headers/Public/Alamofire/Alamofire-iOS.modulemap"; sourceTree = ""; }; + 9555A6B2965DFDC55D0387648293A42F /* Pods-SynchronyFinancial-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SynchronyFinancial-dummy.m"; sourceTree = ""; }; + 9CF8E2718013FE28EA2B513F62CD592B /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist"; sourceTree = ""; }; + A7A590C07A66777331D6859D6A51F6BE /* Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown"; sourceTree = ""; }; + A887B9AEFC28E0F81536EC8A5F82DEE4 /* Response.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Response.swift; path = Source/Response.swift; sourceTree = ""; }; + A8DDCA62346A9286701819B9F049E579 /* SessionManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionManager.swift; path = Source/SessionManager.swift; sourceTree = ""; }; + AFD3ECE7F54DB7F584C5EF2743D9B3CA /* Pods-SynchronyFinancial-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SynchronyFinancial-acknowledgements.plist"; sourceTree = ""; }; + B4CEFB54704C98824E6DD456EE364D63 /* Pods-SynchronyFinancial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial.debug.xcconfig"; sourceTree = ""; }; + B50187719449A01B0AF5EAAAB11CF486 /* Alamofire-iOS.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Alamofire-iOS.xcconfig"; sourceTree = ""; }; + B8432CD9A606E1FDD008F55545694522 /* Pods-SynchronyFinancial-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SynchronyFinancial-acknowledgements.markdown"; sourceTree = ""; }; + B8E2BAAA4D58FAD217366AEB2C6F6303 /* Pods-SynchronyFinancial WatchKit App-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SynchronyFinancial WatchKit App-acknowledgements.plist"; sourceTree = ""; }; + B8F82C8BB9CF77CC85718EB72F1E9FB8 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Source/Result.swift; sourceTree = ""; }; + C098C75CF5A1A0AE043F25CEBE6D3A94 /* ResponseSerialization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResponseSerialization.swift; path = Source/ResponseSerialization.swift; sourceTree = ""; }; + C17C972C596660048C58467D76C70664 /* Alamofire-iOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "Alamofire-iOS-umbrella.h"; path = "../../Headers/Public/Alamofire/Alamofire-iOS-umbrella.h"; sourceTree = ""; }; + C3A3CFC003773DF2181529D4D8E7C75C /* libPods-SynchronyFinancial.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-SynchronyFinancial.a"; path = "libPods-SynchronyFinancial.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + C85F01053044F50A97BF9252488ED3C3 /* Pods-SynchronyFinancial WatchKit Extension.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-SynchronyFinancial WatchKit Extension.modulemap"; sourceTree = ""; }; + D35191BEC74246D30F8BCCC900A65C44 /* ParameterEncoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ParameterEncoding.swift; path = Source/ParameterEncoding.swift; sourceTree = ""; }; + D70416CD1D8FC178C04A02A149C11971 /* Timeline.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Timeline.swift; path = Source/Timeline.swift; sourceTree = ""; }; + DCB0FDE84D687029DD5FFDE4E47C1BBD /* Alamofire-iOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Alamofire-iOS-prefix.pch"; sourceTree = ""; }; + DEACB5D3C3E83582595EE3DA3B42CFD3 /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Source/SessionDelegate.swift; sourceTree = ""; }; + E3FB030C43F304B46B7D13D340F85758 /* Pods-SynchronyFinancial WatchKit App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit App.debug.xcconfig"; sourceTree = ""; }; + E3FD293B6881D7FA4F8F099F9D0E8BDC /* Alamofire-iOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Alamofire-iOS-dummy.m"; sourceTree = ""; }; + E417715AA69FF6BDEEB3690D2A78F441 /* Pods-SynchronyFinancial WatchKit App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SynchronyFinancial WatchKit App.release.xcconfig"; sourceTree = ""; }; + E94C872345A1E81337AC8C19DB3D7DF1 /* NetworkReachabilityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkReachabilityManager.swift; path = Source/NetworkReachabilityManager.swift; sourceTree = ""; }; + EF6EAF4EA7DB08F8A58F4B8E0BA1099D /* Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Request.swift; path = Source/Request.swift; sourceTree = ""; }; + F2A25DA1E05048BC5530EFE869D75150 /* libAlamofire-watchOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libAlamofire-watchOS.a"; path = "libAlamofire-watchOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F926E34C9F3384D6C4EFCCA1FA84B5D3 /* ServerTrustPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServerTrustPolicy.swift; path = Source/ServerTrustPolicy.swift; sourceTree = ""; }; + FC8E1DC5E17A25E87566D8D4BB34A5CA /* AFError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AFError.swift; path = Source/AFError.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 2E7AA0954AF5C85F8A36D7F848B1E6CB /* Frameworks */ = { + 930DD0A8C13B793ADCFD7D25D0E4F052 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 5BC8FC76FBCF1D1CD5BB645032B7635D /* Frameworks */ = { + C0E170A80BF17BE007F1BC2EABA87AC5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - AD5E5763E6BC1B4EBBFEF7B6230F7077 /* Frameworks */ = { + D770F92D7A85955A0FAF2661B972B2B8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D889836E012E42E6050724B9E74CD940 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FEA78C862BA53A2CDE1B886C98A1DE88 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -72,174 +186,285 @@ name = Frameworks; sourceTree = ""; }; - 32A23E08346748F1793F899C5FF672C1 /* SwiftLint */ = { + 1FD7A0395F2B1C872EC1F3973D265410 /* Targets Support Files */ = { isa = PBXGroup; children = ( + EAD8D8028C88033DEC064BBD6DDE6227 /* Pods-SynchronyFinancial */, + 4BDF854502C7AED804AC25F7012574C5 /* Pods-SynchronyFinancial WatchKit App */, + 98597B9F8A6CBD60763720350534BA7B /* Pods-SynchronyFinancial WatchKit Extension */, ); - name = SwiftLint; - path = SwiftLint; + name = "Targets Support Files"; sourceTree = ""; }; - 4F22BAC439AC97E35AA370FF03BF9540 /* Pods-SynchronyFinancial WatchKit Extension */ = { + 4B919E0E1046184ACF1E47EE40C6046D /* Products */ = { isa = PBXGroup; children = ( - A97A3561E549200D718457DE1DA30E70 /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown */, - 457688DD3D6D97D5F9359A9958B638D5 /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist */, - 73414FA9DAEB014677753FA4EC70919F /* Pods-SynchronyFinancial WatchKit Extension-dummy.m */, - AE59890BB0AF9ABE93999F3BA2C48220 /* Pods-SynchronyFinancial WatchKit Extension-frameworks.sh */, - 12A852DC2609D33030D800D26DE0E3FF /* Pods-SynchronyFinancial WatchKit Extension-resources.sh */, - A7709832E45752BA1DB6E6DD56492533 /* Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig */, - 57E684B1EF7582F71059B34345C49933 /* Pods-SynchronyFinancial WatchKit Extension.release.xcconfig */, + 1DFA543FE9FB2C8ADCCAC70C1F268481 /* libAlamofire-iOS.a */, + F2A25DA1E05048BC5530EFE869D75150 /* libAlamofire-watchOS.a */, + C3A3CFC003773DF2181529D4D8E7C75C /* libPods-SynchronyFinancial.a */, + 0496E630215776378A9F46EB6C1A3DF0 /* libPods-SynchronyFinancial WatchKit App.a */, + 4259FFBBEFB620F748F6C7933ECE173A /* libPods-SynchronyFinancial WatchKit Extension.a */, ); - name = "Pods-SynchronyFinancial WatchKit Extension"; - path = "Target Support Files/Pods-SynchronyFinancial WatchKit Extension"; + name = Products; sourceTree = ""; }; - 7DB346D0F39D3F0E887471402A8071AB = { + 4BDF854502C7AED804AC25F7012574C5 /* Pods-SynchronyFinancial WatchKit App */ = { isa = PBXGroup; children = ( - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 0F8D2E47FE03D3B91B51069F7C273AF4 /* Frameworks */, - 9758CC519AE2C57A9659FFC01AAD26F9 /* Pods */, - F36EDCFBD2119ED70FBA19701BF6B4C1 /* Products */, - EB1AF7AA8216950CB58580C1F1B90CCC /* Targets Support Files */, + 72E4CE044ED07D65A3422CA2D0E23AA8 /* Pods-SynchronyFinancial WatchKit App.modulemap */, + A7A590C07A66777331D6859D6A51F6BE /* Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown */, + B8E2BAAA4D58FAD217366AEB2C6F6303 /* Pods-SynchronyFinancial WatchKit App-acknowledgements.plist */, + 4CB542604CFB0314507EEC5225EB4B64 /* Pods-SynchronyFinancial WatchKit App-dummy.m */, + 5487630E77717246F089B8C039034743 /* Pods-SynchronyFinancial WatchKit App-frameworks.sh */, + 2B4527DE8A4A826FD88BE08AFFEBEEA8 /* Pods-SynchronyFinancial WatchKit App-resources.sh */, + 848A32D3ABE543896C0E61DC0DB2DC48 /* Pods-SynchronyFinancial WatchKit App-umbrella.h */, + E3FB030C43F304B46B7D13D340F85758 /* Pods-SynchronyFinancial WatchKit App.debug.xcconfig */, + E417715AA69FF6BDEEB3690D2A78F441 /* Pods-SynchronyFinancial WatchKit App.release.xcconfig */, ); + name = "Pods-SynchronyFinancial WatchKit App"; + path = "Target Support Files/Pods-SynchronyFinancial WatchKit App"; sourceTree = ""; }; - 9758CC519AE2C57A9659FFC01AAD26F9 /* Pods */ = { + 6C56087DE0912120757A4EC1CD7AF0FB /* Pods */ = { isa = PBXGroup; children = ( - 32A23E08346748F1793F899C5FF672C1 /* SwiftLint */, + C24284A636025FF7983CBF6397728C49 /* Alamofire */, + 7138FDC4C56623C37A67C4D2B5F144BD /* SwiftLint */, ); name = Pods; sourceTree = ""; }; - A70A2C65372B1E1C1D5A8080A9B38845 /* Pods-SynchronyFinancial */ = { + 7138FDC4C56623C37A67C4D2B5F144BD /* SwiftLint */ = { isa = PBXGroup; children = ( - 3313A253E1368C5838C70D2E4BCF6805 /* Pods-SynchronyFinancial-acknowledgements.markdown */, - 50F7E546853B4F5A1AECB55BD2BE3608 /* Pods-SynchronyFinancial-acknowledgements.plist */, - 223A928E0610C878C2936F0B3F67F128 /* Pods-SynchronyFinancial-dummy.m */, - 0EA3ACB934ED5CC20B03ED0284DC7ED6 /* Pods-SynchronyFinancial-frameworks.sh */, - 0C620C5446A023E3F572797CDF582D02 /* Pods-SynchronyFinancial-resources.sh */, - A9B5D092ECDBAB4F9C04EF1C1102C7FD /* Pods-SynchronyFinancial.debug.xcconfig */, - B821AEADF995C7AF278DB3565B4510D0 /* Pods-SynchronyFinancial.release.xcconfig */, ); - name = "Pods-SynchronyFinancial"; - path = "Target Support Files/Pods-SynchronyFinancial"; + name = SwiftLint; + path = SwiftLint; sourceTree = ""; }; - DD936CA7C926E755466046D5E6BD160B /* Pods-SynchronyFinancial WatchKit App */ = { + 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( - E88AB63B9BC4A9BC88EBEEBA4E823161 /* Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown */, - D2712C00382A53A331ECBA6531436563 /* Pods-SynchronyFinancial WatchKit App-acknowledgements.plist */, - 7F5DD302624CB5C74B7F2F41755B5F1E /* Pods-SynchronyFinancial WatchKit App-dummy.m */, - 1537C7EC3F51C446C8E8D32F9D470930 /* Pods-SynchronyFinancial WatchKit App-frameworks.sh */, - 3D8FBB1F320C4DC436EF5B6981045F78 /* Pods-SynchronyFinancial WatchKit App-resources.sh */, - CAD575327346729A8CA1067BF0E8940B /* Pods-SynchronyFinancial WatchKit App.debug.xcconfig */, - FA232DDB2CBE07129517FCB5EC00D516 /* Pods-SynchronyFinancial WatchKit App.release.xcconfig */, + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + 0F8D2E47FE03D3B91B51069F7C273AF4 /* Frameworks */, + 6C56087DE0912120757A4EC1CD7AF0FB /* Pods */, + 4B919E0E1046184ACF1E47EE40C6046D /* Products */, + 1FD7A0395F2B1C872EC1F3973D265410 /* Targets Support Files */, ); - name = "Pods-SynchronyFinancial WatchKit App"; - path = "Target Support Files/Pods-SynchronyFinancial WatchKit App"; sourceTree = ""; }; - EB1AF7AA8216950CB58580C1F1B90CCC /* Targets Support Files */ = { + 98597B9F8A6CBD60763720350534BA7B /* Pods-SynchronyFinancial WatchKit Extension */ = { isa = PBXGroup; children = ( - A70A2C65372B1E1C1D5A8080A9B38845 /* Pods-SynchronyFinancial */, - DD936CA7C926E755466046D5E6BD160B /* Pods-SynchronyFinancial WatchKit App */, - 4F22BAC439AC97E35AA370FF03BF9540 /* Pods-SynchronyFinancial WatchKit Extension */, + C85F01053044F50A97BF9252488ED3C3 /* Pods-SynchronyFinancial WatchKit Extension.modulemap */, + 2CEB3B037F3EDCFE35FE79D27D7801FF /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown */, + 9CF8E2718013FE28EA2B513F62CD592B /* Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist */, + 37BDDE6101FAF9052E04078C570E0CB5 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m */, + 2B6E27EFC7E2A6157C6AD726AD1B26E0 /* Pods-SynchronyFinancial WatchKit Extension-frameworks.sh */, + 487E55B2BBEFDD99BE20143A1E7DF181 /* Pods-SynchronyFinancial WatchKit Extension-resources.sh */, + 22D3304892D7984CB8C48B7D236AC3F6 /* Pods-SynchronyFinancial WatchKit Extension-umbrella.h */, + 4B98B3A9F78869E2C0EC19625A2BE917 /* Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig */, + 1F31328046BB381D71AAFDF15525D78B /* Pods-SynchronyFinancial WatchKit Extension.release.xcconfig */, ); - name = "Targets Support Files"; + name = "Pods-SynchronyFinancial WatchKit Extension"; + path = "Target Support Files/Pods-SynchronyFinancial WatchKit Extension"; sourceTree = ""; }; - F36EDCFBD2119ED70FBA19701BF6B4C1 /* Products */ = { + B21B012F11279787B3A2610B6A48B020 /* Support Files */ = { isa = PBXGroup; children = ( - 88C8CC772368957E67DC04939293976C /* libPods-SynchronyFinancial.a */, - 63744D3728BF84FDF191D7F7CE4AD656 /* libPods-SynchronyFinancial WatchKit App.a */, - 38B1BBE679F86F1EDCEC91ADF251D892 /* libPods-SynchronyFinancial WatchKit Extension.a */, + 94C7891EDD57DC7CE6A69164AAAB6BE9 /* Alamofire-iOS.modulemap */, + B50187719449A01B0AF5EAAAB11CF486 /* Alamofire-iOS.xcconfig */, + E3FD293B6881D7FA4F8F099F9D0E8BDC /* Alamofire-iOS-dummy.m */, + DCB0FDE84D687029DD5FFDE4E47C1BBD /* Alamofire-iOS-prefix.pch */, + C17C972C596660048C58467D76C70664 /* Alamofire-iOS-umbrella.h */, + 79B982FACBEE749DC74DFB3A916A2A56 /* Alamofire-watchOS.modulemap */, + 1D108A04C250B757FFCA530C141F1214 /* Alamofire-watchOS.xcconfig */, + 726B125FA1325683D7E7A28E2E51F269 /* Alamofire-watchOS-dummy.m */, + 39388D231E4A59E61553D8130BB544EB /* Alamofire-watchOS-prefix.pch */, + 23E68A43BE6AEE7C774A6C2F81FA32E1 /* Alamofire-watchOS-umbrella.h */, ); - name = Products; + name = "Support Files"; + path = "../Target Support Files/Alamofire-iOS"; + sourceTree = ""; + }; + C24284A636025FF7983CBF6397728C49 /* Alamofire */ = { + isa = PBXGroup; + children = ( + FC8E1DC5E17A25E87566D8D4BB34A5CA /* AFError.swift */, + 938335C8A86618E6479B72666E8B3472 /* Alamofire.swift */, + 890C65E53958E5AE67698437CA76F9E5 /* DispatchQueue+Alamofire.swift */, + 2B3A23ED84B2A322445815BE53FCDC7A /* MultipartFormData.swift */, + E94C872345A1E81337AC8C19DB3D7DF1 /* NetworkReachabilityManager.swift */, + 0BB2C4D8119B2B3386DF57724B6FFE42 /* Notifications.swift */, + D35191BEC74246D30F8BCCC900A65C44 /* ParameterEncoding.swift */, + EF6EAF4EA7DB08F8A58F4B8E0BA1099D /* Request.swift */, + A887B9AEFC28E0F81536EC8A5F82DEE4 /* Response.swift */, + C098C75CF5A1A0AE043F25CEBE6D3A94 /* ResponseSerialization.swift */, + B8F82C8BB9CF77CC85718EB72F1E9FB8 /* Result.swift */, + F926E34C9F3384D6C4EFCCA1FA84B5D3 /* ServerTrustPolicy.swift */, + DEACB5D3C3E83582595EE3DA3B42CFD3 /* SessionDelegate.swift */, + A8DDCA62346A9286701819B9F049E579 /* SessionManager.swift */, + 23E743C86FF4065DCC16BBD3D2317EDB /* TaskDelegate.swift */, + D70416CD1D8FC178C04A02A149C11971 /* Timeline.swift */, + 3A86C55E839A0051646DA6AB8952C506 /* Validation.swift */, + B21B012F11279787B3A2610B6A48B020 /* Support Files */, + ); + name = Alamofire; + path = Alamofire; + sourceTree = ""; + }; + EAD8D8028C88033DEC064BBD6DDE6227 /* Pods-SynchronyFinancial */ = { + isa = PBXGroup; + children = ( + 5A843197C4CAEDE101D9A76A0A416E9D /* Pods-SynchronyFinancial.modulemap */, + B8432CD9A606E1FDD008F55545694522 /* Pods-SynchronyFinancial-acknowledgements.markdown */, + AFD3ECE7F54DB7F584C5EF2743D9B3CA /* Pods-SynchronyFinancial-acknowledgements.plist */, + 9555A6B2965DFDC55D0387648293A42F /* Pods-SynchronyFinancial-dummy.m */, + 4EF87963D687D12C78C9CAFC3E389987 /* Pods-SynchronyFinancial-frameworks.sh */, + 797029C829F77B6F8D46FD6DBD1B1B38 /* Pods-SynchronyFinancial-resources.sh */, + 03E19667BC72E1E238261E24CD564E30 /* Pods-SynchronyFinancial-umbrella.h */, + B4CEFB54704C98824E6DD456EE364D63 /* Pods-SynchronyFinancial.debug.xcconfig */, + 668280BA4A5081F50698A173BCC0E7FE /* Pods-SynchronyFinancial.release.xcconfig */, + ); + name = "Pods-SynchronyFinancial"; + path = "Target Support Files/Pods-SynchronyFinancial"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 92B4ED6DCD743098B9FDCE477D9EDA78 /* Headers */ = { + 673FF44DE35DAEE1A900F02692A1D300 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4F434A210C06FA4F4194A3CDA5C39F0C /* Alamofire-watchOS-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 92C0E3BF31523014B7ABF68ED101830F /* Headers */ = { + 8F117F3D0D48486C46771567905C158D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + E49DE408E8EA7B65B1AF4DC004F6D099 /* Pods-SynchronyFinancial-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - D84E63FE99912DE58C8FACAA1B0D7369 /* Headers */ = { + D65BD481959A0EE865F9905D4014C703 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 42788A9753A4D04D53BEA70CBB7DF705 /* Pods-SynchronyFinancial WatchKit App-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D72D5EAE296924246E77932B36CEB218 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1BDC0921F64F29554B83E7B70395CB11 /* Alamofire-iOS-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F1F3DC37957E31C90723FDA4E5E68105 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D45D8BCE32A05EDCBB89D2C296A46E1 /* Pods-SynchronyFinancial WatchKit Extension-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 1C1EE2CC22706BBE47E77895193D70C2 /* Pods-SynchronyFinancial WatchKit Extension */ = { + 449BDE5D9D406B30E8E4E97CD9DF4F01 /* Alamofire-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9DF94BDE67A39C1D1610F678A11EEF2D /* Build configuration list for PBXNativeTarget "Alamofire-iOS" */; + buildPhases = ( + D72D5EAE296924246E77932B36CEB218 /* Headers */, + 929597E698512C166FFDA3BAEF162568 /* Sources */, + D770F92D7A85955A0FAF2661B972B2B8 /* Frameworks */, + B6B2C43A05C8D73DE3F6B92317A11D09 /* Copy generated compatibility header */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Alamofire-iOS"; + productName = "Alamofire-iOS"; + productReference = 1DFA543FE9FB2C8ADCCAC70C1F268481 /* libAlamofire-iOS.a */; + productType = "com.apple.product-type.library.static"; + }; + 60B62C23016A64A81CA9B683B839D5ED /* Pods-SynchronyFinancial WatchKit Extension */ = { isa = PBXNativeTarget; - buildConfigurationList = 7ED3A90A9B63085342B6E68F113EBB1C /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit Extension" */; + buildConfigurationList = 10AAD650771EED2F9D0C573C11FC73B9 /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit Extension" */; buildPhases = ( - 92B4ED6DCD743098B9FDCE477D9EDA78 /* Headers */, - A06B22EFFF1617D2752DE0DC6A33D276 /* Sources */, - AD5E5763E6BC1B4EBBFEF7B6230F7077 /* Frameworks */, + F1F3DC37957E31C90723FDA4E5E68105 /* Headers */, + B530CB31DC7EC1F30056F7FD61E3B418 /* Sources */, + D889836E012E42E6050724B9E74CD940 /* Frameworks */, ); buildRules = ( ); dependencies = ( + DA96FDFFDD87D65BA2324671F9B003BF /* PBXTargetDependency */, ); name = "Pods-SynchronyFinancial WatchKit Extension"; productName = "Pods-SynchronyFinancial WatchKit Extension"; - productReference = 38B1BBE679F86F1EDCEC91ADF251D892 /* libPods-SynchronyFinancial WatchKit Extension.a */; + productReference = 4259FFBBEFB620F748F6C7933ECE173A /* libPods-SynchronyFinancial WatchKit Extension.a */; productType = "com.apple.product-type.library.static"; }; - 27A74EF48A858B2F847AC95666B50E0D /* Pods-SynchronyFinancial WatchKit App */ = { + 783377E47E8E56532B705F6FA7EBB00A /* Pods-SynchronyFinancial WatchKit App */ = { isa = PBXNativeTarget; - buildConfigurationList = 8FA97F3A7461FB0EB8A5EBFF0737DF5A /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit App" */; + buildConfigurationList = 2D3CD921CBC369D133CBEE2FAC6EAAEB /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit App" */; buildPhases = ( - 92C0E3BF31523014B7ABF68ED101830F /* Headers */, - 751B861C9D0A158FF16048310B67831E /* Sources */, - 2E7AA0954AF5C85F8A36D7F848B1E6CB /* Frameworks */, + D65BD481959A0EE865F9905D4014C703 /* Headers */, + 429FE9928BC31A368839DB4DB1C49CEF /* Sources */, + FEA78C862BA53A2CDE1B886C98A1DE88 /* Frameworks */, ); buildRules = ( ); dependencies = ( + 96FD4E7AF815EF9590FDEA4E29448A46 /* PBXTargetDependency */, ); name = "Pods-SynchronyFinancial WatchKit App"; productName = "Pods-SynchronyFinancial WatchKit App"; - productReference = 63744D3728BF84FDF191D7F7CE4AD656 /* libPods-SynchronyFinancial WatchKit App.a */; + productReference = 0496E630215776378A9F46EB6C1A3DF0 /* libPods-SynchronyFinancial WatchKit App.a */; + productType = "com.apple.product-type.library.static"; + }; + B8E4738C39F45964F0C646DC61C880BB /* Alamofire-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 79244342F421614947C2179DA0C09388 /* Build configuration list for PBXNativeTarget "Alamofire-watchOS" */; + buildPhases = ( + 673FF44DE35DAEE1A900F02692A1D300 /* Headers */, + 3D7C54143FBBF306C65A41DD05558A1D /* Sources */, + 930DD0A8C13B793ADCFD7D25D0E4F052 /* Frameworks */, + 30CEBA13BC33A9D5136022BBEB284FA3 /* Copy generated compatibility header */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Alamofire-watchOS"; + productName = "Alamofire-watchOS"; + productReference = F2A25DA1E05048BC5530EFE869D75150 /* libAlamofire-watchOS.a */; productType = "com.apple.product-type.library.static"; }; - D12A6ED6D135786818BC2A5C2641A8FF /* Pods-SynchronyFinancial */ = { + DB714C3FFF0B37B02D9E4187590BA927 /* Pods-SynchronyFinancial */ = { isa = PBXNativeTarget; - buildConfigurationList = C4C1154F80F085EEB9DED2E7F9FACC8F /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial" */; + buildConfigurationList = 77BA9BB120F827AE79B3B68C7D732843 /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial" */; buildPhases = ( - D84E63FE99912DE58C8FACAA1B0D7369 /* Headers */, - 89247EC50CC0EE54A47E9F73B2C10C1F /* Sources */, - 5BC8FC76FBCF1D1CD5BB645032B7635D /* Frameworks */, + 8F117F3D0D48486C46771567905C158D /* Headers */, + E3EF4C962FED7A1A769F38CA5D48A4D9 /* Sources */, + C0E170A80BF17BE007F1BC2EABA87AC5 /* Frameworks */, ); buildRules = ( ); dependencies = ( + 68269D645449FF719B0026EF5E7BE11E /* PBXTargetDependency */, ); name = "Pods-SynchronyFinancial"; productName = "Pods-SynchronyFinancial"; - productReference = 88C8CC772368957E67DC04939293976C /* libPods-SynchronyFinancial.a */; + productReference = C3A3CFC003773DF2181529D4D8E7C75C /* libPods-SynchronyFinancial.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -259,76 +484,207 @@ en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = F36EDCFBD2119ED70FBA19701BF6B4C1 /* Products */; + productRefGroup = 4B919E0E1046184ACF1E47EE40C6046D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - D12A6ED6D135786818BC2A5C2641A8FF /* Pods-SynchronyFinancial */, - 27A74EF48A858B2F847AC95666B50E0D /* Pods-SynchronyFinancial WatchKit App */, - 1C1EE2CC22706BBE47E77895193D70C2 /* Pods-SynchronyFinancial WatchKit Extension */, + 449BDE5D9D406B30E8E4E97CD9DF4F01 /* Alamofire-iOS */, + B8E4738C39F45964F0C646DC61C880BB /* Alamofire-watchOS */, + DB714C3FFF0B37B02D9E4187590BA927 /* Pods-SynchronyFinancial */, + 783377E47E8E56532B705F6FA7EBB00A /* Pods-SynchronyFinancial WatchKit App */, + 60B62C23016A64A81CA9B683B839D5ED /* Pods-SynchronyFinancial WatchKit Extension */, ); }; /* End PBXProject section */ +/* Begin PBXShellScriptBuildPhase section */ + 30CEBA13BC33A9D5136022BBEB284FA3 /* Copy generated compatibility header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h", + "${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-watchOS.modulemap", + "${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-watchOS-umbrella.h", + ); + name = "Copy generated compatibility header"; + outputFileListPaths = ( + ); + outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap", + "${BUILT_PRODUCTS_DIR}/Alamofire-watchOS-umbrella.h", + "${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "COMPATIBILITY_HEADER_PATH=\"${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h\"\nMODULE_MAP_PATH=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap\"\n\nditto \"${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h\" \"${COMPATIBILITY_HEADER_PATH}\"\nditto \"${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-watchOS.modulemap\" \"${MODULE_MAP_PATH}\"\nditto \"${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-watchOS-umbrella.h\" \"${BUILT_PRODUCTS_DIR}\"\nprintf \"\\n\\nmodule ${PRODUCT_MODULE_NAME}.Swift {\\n header \\\"${COMPATIBILITY_HEADER_PATH}\\\"\\n requires objc\\n}\\n\" >> \"${MODULE_MAP_PATH}\"\n"; + showEnvVarsInLog = 1; + }; + B6B2C43A05C8D73DE3F6B92317A11D09 /* Copy generated compatibility header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h", + "${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-iOS.modulemap", + "${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-iOS-umbrella.h", + ); + name = "Copy generated compatibility header"; + outputFileListPaths = ( + ); + outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap", + "${BUILT_PRODUCTS_DIR}/Alamofire-iOS-umbrella.h", + "${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "COMPATIBILITY_HEADER_PATH=\"${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h\"\nMODULE_MAP_PATH=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap\"\n\nditto \"${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h\" \"${COMPATIBILITY_HEADER_PATH}\"\nditto \"${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-iOS.modulemap\" \"${MODULE_MAP_PATH}\"\nditto \"${PODS_ROOT}/Headers/Public/Alamofire/Alamofire-iOS-umbrella.h\" \"${BUILT_PRODUCTS_DIR}\"\nprintf \"\\n\\nmodule ${PRODUCT_MODULE_NAME}.Swift {\\n header \\\"${COMPATIBILITY_HEADER_PATH}\\\"\\n requires objc\\n}\\n\" >> \"${MODULE_MAP_PATH}\"\n"; + showEnvVarsInLog = 1; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ - 751B861C9D0A158FF16048310B67831E /* Sources */ = { + 3D7C54143FBBF306C65A41DD05558A1D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C599707E21CF41062AB104EFA961B29 /* AFError.swift in Sources */, + AFB761B750134903DB4DC8E80595D3EC /* Alamofire-watchOS-dummy.m in Sources */, + 8EA6A1E73DF672BBBC94B1D9BB685DDD /* Alamofire.swift in Sources */, + 98EBB2E00D23DAD35E2E3E1F4920557D /* DispatchQueue+Alamofire.swift in Sources */, + 433CB78DFCA4AEEB4799FE22E448E783 /* MultipartFormData.swift in Sources */, + 386CECFA45DFF6191BECE87AF9F3E3DF /* NetworkReachabilityManager.swift in Sources */, + F85151956AE3CFEEAA2B1B626C9FA4FC /* Notifications.swift in Sources */, + 60F5CDD4E36FECB47E136B191AAC39C7 /* ParameterEncoding.swift in Sources */, + B51C64A54D1D60EE396D519B0EF7B98C /* Request.swift in Sources */, + E6ADB328EEFDD2769CD7B5216F455968 /* Response.swift in Sources */, + 8995E81689ED6E5D86A4A549A736ABD5 /* ResponseSerialization.swift in Sources */, + BC8B935096B146374B4439F42AFA7421 /* Result.swift in Sources */, + D40E7525C96B28DEC2E260D9EFD66E67 /* ServerTrustPolicy.swift in Sources */, + E108694CE400C627D9A28BF8EFCEDC83 /* SessionDelegate.swift in Sources */, + EF1D70E53200EE4CB2F21890CF75B1D2 /* SessionManager.swift in Sources */, + FC686378DFFBEFB17B00BBD94333B7CC /* TaskDelegate.swift in Sources */, + 763240E338AFF56BE6B70F65DC438045 /* Timeline.swift in Sources */, + ADE79C2381EED50B80561A6229B84CA9 /* Validation.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 429FE9928BC31A368839DB4DB1C49CEF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CDB9D5D771EC41C24E5FC025CDD2F02D /* Pods-SynchronyFinancial WatchKit App-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 929597E698512C166FFDA3BAEF162568 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9EE883E312A828174A57FC699BEE740B /* Pods-SynchronyFinancial WatchKit App-dummy.m in Sources */, + 5248A82654243159E7E3BF56537E9DF3 /* AFError.swift in Sources */, + 9EC4FEE90C2B8607BB2B1620A528ACAD /* Alamofire-iOS-dummy.m in Sources */, + 97D1C0EA155278A4C435B89B772CEAFB /* Alamofire.swift in Sources */, + 4A90EE80279B2A3B26B176543654C368 /* DispatchQueue+Alamofire.swift in Sources */, + F68AF157549FE798EEBCEB19B1FD28B0 /* MultipartFormData.swift in Sources */, + 702E11E33684ADEF848F6747405051BA /* NetworkReachabilityManager.swift in Sources */, + DD2222A99E09A2E7FD6F721A3C32E40F /* Notifications.swift in Sources */, + C59F2B590B0C69031ACB9170812B3AF6 /* ParameterEncoding.swift in Sources */, + DBFFF690F7E108F7C5A3D3D76871D557 /* Request.swift in Sources */, + 82EADC7327F5F572A58D410DCF3DE3BF /* Response.swift in Sources */, + 9A54CB8CA91C572E283699874260036C /* ResponseSerialization.swift in Sources */, + 16C7AC67BDFE60A674BC8A4F508DD60C /* Result.swift in Sources */, + 60035FFA16C07A85E68CE346939F2B6F /* ServerTrustPolicy.swift in Sources */, + 211C56E073E89711CFC0B564D6DE3DBC /* SessionDelegate.swift in Sources */, + 17F5A3C3C1FF68BF98C5C67214A10DA8 /* SessionManager.swift in Sources */, + 922D040FE414B746702500EBA4E0A64C /* TaskDelegate.swift in Sources */, + AD5A8C570F6D58F4DEBD0EC478B34996 /* Timeline.swift in Sources */, + 7F3D2A1E85D34B7B1CB3A244C179C700 /* Validation.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 89247EC50CC0EE54A47E9F73B2C10C1F /* Sources */ = { + B530CB31DC7EC1F30056F7FD61E3B418 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C9ED209725BA93A2E09CE9745A7F124A /* Pods-SynchronyFinancial-dummy.m in Sources */, + 06AD8F515AA607C8CB47865D93E97E16 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A06B22EFFF1617D2752DE0DC6A33D276 /* Sources */ = { + E3EF4C962FED7A1A769F38CA5D48A4D9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 40786BCC70FAE2E0979F6BE1509C1D67 /* Pods-SynchronyFinancial WatchKit Extension-dummy.m in Sources */, + 1A0FF2D7AB93FEAEABFB337A470FBCF4 /* Pods-SynchronyFinancial-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 68269D645449FF719B0026EF5E7BE11E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Alamofire-iOS"; + target = 449BDE5D9D406B30E8E4E97CD9DF4F01 /* Alamofire-iOS */; + targetProxy = 73BA8BAB2DFC05CA43738D9049E43B08 /* PBXContainerItemProxy */; + }; + 96FD4E7AF815EF9590FDEA4E29448A46 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Alamofire-watchOS"; + target = B8E4738C39F45964F0C646DC61C880BB /* Alamofire-watchOS */; + targetProxy = B2FB7006531883F892E7CA8DE39A304D /* PBXContainerItemProxy */; + }; + DA96FDFFDD87D65BA2324671F9B003BF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Alamofire-watchOS"; + target = B8E4738C39F45964F0C646DC61C880BB /* Alamofire-watchOS */; + targetProxy = E75DF8434FC6AE4EA1080FA7F88FFAE7 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ - 3C41C041CAECCC4D12946C85E5472EC3 /* Release */ = { + 2826682D386C6B0BC3B233227C591921 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FA232DDB2CBE07129517FCB5EC00D516 /* Pods-SynchronyFinancial WatchKit App.release.xcconfig */; + baseConfigurationReference = 1D108A04C250B757FFCA530C141F1214 /* Alamofire-watchOS.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + APPLICATION_EXTENSION_API_ONLY = YES; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - MACH_O_TYPE = staticlib; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire-watchOS/Alamofire-watchOS-prefix.pch"; + MODULEMAP_FILE = "Headers/Public/Alamofire/Alamofire-watchOS.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = "Alamofire-watchOS"; + PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 4; VALIDATE_PRODUCT = YES; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Release; }; - 52D0887D5BABF294BE8CB7D96E8721C3 /* Debug */ = { + 328F6C25659258D7ECF1BC18DAFE9452 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A7709832E45752BA1DB6E6DD56492533 /* Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig */; + baseConfigurationReference = E3FB030C43F304B46B7D13D340F85758 /* Pods-SynchronyFinancial WatchKit App.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - APPLICATION_EXTENSION_API_ONLY = YES; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -340,9 +696,9 @@ }; name = Debug; }; - 5AB7AC58FF902F8526D3B66AFCBB77A6 /* Debug */ = { + 5A9651F5FCF4C06FF4936FA8C8D7CA44 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A9B5D092ECDBAB4F9C04EF1C1102C7FD /* Pods-SynchronyFinancial.debug.xcconfig */; + baseConfigurationReference = B4CEFB54704C98824E6DD456EE364D63 /* Pods-SynchronyFinancial.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -352,6 +708,7 @@ "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; IPHONEOS_DEPLOYMENT_TARGET = 10.0; MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -362,15 +719,17 @@ }; name = Debug; }; - 68BF50CCF2258A937C166AFCCEF45E4D /* Debug */ = { + 5FA936D8EA4A2A663DD9E083BD8D489F /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CAD575327346729A8CA1067BF0E8940B /* Pods-SynchronyFinancial WatchKit App.debug.xcconfig */; + baseConfigurationReference = 4B98B3A9F78869E2C0EC19625A2BE917 /* Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + APPLICATION_EXTENSION_API_ONLY = YES; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -382,28 +741,30 @@ }; name = Debug; }; - 79E87A9D3BD467B10146DDA2F222D68C /* Release */ = { + 6CE353B2F3CA375A78075020310BC0C6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B821AEADF995C7AF278DB3565B4510D0 /* Pods-SynchronyFinancial.release.xcconfig */; + baseConfigurationReference = 1D108A04C250B757FFCA530C141F1214 /* Alamofire-watchOS.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; + APPLICATION_EXTENSION_API_ONLY = YES; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACH_O_TYPE = staticlib; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire-watchOS/Alamofire-watchOS-prefix.pch"; + MODULEMAP_FILE = "Headers/Public/Alamofire/Alamofire-watchOS.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = "Alamofire-watchOS"; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = watchos; SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 2.0; }; - name = Release; + name = Debug; }; 7D7EDC43F020C2C42F612DC0E341C8C6 /* Debug */ = { isa = XCBuildConfiguration; @@ -472,6 +833,30 @@ }; name = Debug; }; + 94B3714CCC3E8BCE8A3517E981F5E68D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 668280BA4A5081F50698A173BCC0E7FE /* Pods-SynchronyFinancial.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; 9A6A850AEE71AB7B9400CA88CCFA23C5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -535,9 +920,34 @@ }; name = Release; }; - C315109CA0EE7EAF8EDEA70D28B01FA1 /* Release */ = { + C2FDEE3877470D3BDCBB8746006A8D9C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B50187719449A01B0AF5EAAAB11CF486 /* Alamofire-iOS.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire-iOS/Alamofire-iOS-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MODULEMAP_FILE = "Headers/Public/Alamofire/Alamofire-iOS.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = "Alamofire-iOS"; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + CD1CF033ECB231DEC4E9F886E6B87065 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 57E684B1EF7582F71059B34345C49933 /* Pods-SynchronyFinancial WatchKit Extension.release.xcconfig */; + baseConfigurationReference = 1F31328046BB381D71AAFDF15525D78B /* Pods-SynchronyFinancial WatchKit Extension.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; APPLICATION_EXTENSION_API_ONLY = YES; @@ -545,6 +955,29 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 4; + VALIDATE_PRODUCT = YES; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; + EA927A86427CBA927BDE69A2E345E4EC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E417715AA69FF6BDEEB3690D2A78F441 /* Pods-SynchronyFinancial WatchKit App.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -557,9 +990,53 @@ }; name = Release; }; + F29D542AE3B19C8ED97D31B6B4586EEC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B50187719449A01B0AF5EAAAB11CF486 /* Alamofire-iOS.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/Alamofire-iOS/Alamofire-iOS-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MODULEMAP_FILE = "Headers/Public/Alamofire/Alamofire-iOS.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = Alamofire; + PRODUCT_NAME = "Alamofire-iOS"; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 10AAD650771EED2F9D0C573C11FC73B9 /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5FA936D8EA4A2A663DD9E083BD8D489F /* Debug */, + CD1CF033ECB231DEC4E9F886E6B87065 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D3CD921CBC369D133CBEE2FAC6EAAEB /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 328F6C25659258D7ECF1BC18DAFE9452 /* Debug */, + EA927A86427CBA927BDE69A2E345E4EC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -569,29 +1046,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7ED3A90A9B63085342B6E68F113EBB1C /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit Extension" */ = { + 77BA9BB120F827AE79B3B68C7D732843 /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial" */ = { isa = XCConfigurationList; buildConfigurations = ( - 52D0887D5BABF294BE8CB7D96E8721C3 /* Debug */, - C315109CA0EE7EAF8EDEA70D28B01FA1 /* Release */, + 5A9651F5FCF4C06FF4936FA8C8D7CA44 /* Debug */, + 94B3714CCC3E8BCE8A3517E981F5E68D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8FA97F3A7461FB0EB8A5EBFF0737DF5A /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial WatchKit App" */ = { + 79244342F421614947C2179DA0C09388 /* Build configuration list for PBXNativeTarget "Alamofire-watchOS" */ = { isa = XCConfigurationList; buildConfigurations = ( - 68BF50CCF2258A937C166AFCCEF45E4D /* Debug */, - 3C41C041CAECCC4D12946C85E5472EC3 /* Release */, + 6CE353B2F3CA375A78075020310BC0C6 /* Debug */, + 2826682D386C6B0BC3B233227C591921 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C4C1154F80F085EEB9DED2E7F9FACC8F /* Build configuration list for PBXNativeTarget "Pods-SynchronyFinancial" */ = { + 9DF94BDE67A39C1D1610F678A11EEF2D /* Build configuration list for PBXNativeTarget "Alamofire-iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( - 5AB7AC58FF902F8526D3B66AFCBB77A6 /* Debug */, - 79E87A9D3BD467B10146DDA2F222D68C /* Release */, + C2FDEE3877470D3BDCBB8746006A8D9C /* Debug */, + F29D542AE3B19C8ED97D31B6B4586EEC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit App.xcscheme b/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit App.xcscheme index 7e67ff6..d333a58 100644 --- a/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit App.xcscheme +++ b/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit App.xcscheme @@ -14,7 +14,7 @@ buildForArchiving = "YES"> diff --git a/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit Extension.xcscheme b/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit Extension.xcscheme index 69addba..0e20bbd 100644 --- a/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit Extension.xcscheme +++ b/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial WatchKit Extension.xcscheme @@ -14,7 +14,7 @@ buildForArchiving = "YES"> diff --git a/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial.xcscheme b/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial.xcscheme index 0720785..12d21e9 100644 --- a/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial.xcscheme +++ b/SynchronyFinancial/Pods/Pods.xcodeproj/xcuserdata/alanmaynard.xcuserdatad/xcschemes/Pods-SynchronyFinancial.xcscheme @@ -14,7 +14,7 @@ buildForArchiving = "YES"> diff --git a/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS-dummy.m b/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS-dummy.m new file mode 100644 index 0000000..e1abb30 --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Alamofire_iOS : NSObject +@end +@implementation PodsDummy_Alamofire_iOS +@end diff --git a/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS-prefix.pch b/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS-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/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS.xcconfig new file mode 100644 index 0000000..b4ac99a --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Alamofire-iOS/Alamofire-iOS.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS-dummy.m b/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS-dummy.m new file mode 100644 index 0000000..8a0f66d --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Alamofire_watchOS : NSObject +@end +@implementation PodsDummy_Alamofire_watchOS +@end diff --git a/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS-prefix.pch b/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS-prefix.pch new file mode 100644 index 0000000..e33fc32 --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS-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/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS.xcconfig new file mode 100644 index 0000000..849ae5b --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Alamofire-watchOS/Alamofire-watchOS.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown index d8c5fed..8b3a377 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.markdown @@ -1,6 +1,29 @@ # Acknowledgements This application makes use of the following third party libraries: +## Alamofire + +Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +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. + + ## SwiftLint The MIT License (MIT) diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.plist b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.plist index 88fb231..6a14367 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.plist +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-acknowledgements.plist @@ -12,6 +12,35 @@ Type PSGroupSpecifier + + FooterText + Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +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. + + License + MIT + Title + Alamofire + Type + PSGroupSpecifier + FooterText The MIT License (MIT) diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-umbrella.h b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-umbrella.h new file mode 100644 index 0000000..69fd3b6 --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App-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_SynchronyFinancial_WatchKit_AppVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_SynchronyFinancial_WatchKit_AppVersionString[]; + diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.debug.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.debug.xcconfig index 729bac8..fb04101 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.debug.xcconfig +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.debug.xcconfig @@ -1,6 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_LDFLAGS = $(inherited) -ObjC +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" +OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Alamofire-watchOS" +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" $(inherited) "-D" "COCOAPODS" 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 +SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.modulemap b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.modulemap new file mode 100644 index 0000000..d97a7cc --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.modulemap @@ -0,0 +1,6 @@ +module Pods_SynchronyFinancial_WatchKit_App { + umbrella header "Pods-SynchronyFinancial WatchKit App-umbrella.h" + + export * + module * { export * } +} diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.release.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.release.xcconfig index 729bac8..fb04101 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.release.xcconfig +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit App/Pods-SynchronyFinancial WatchKit App.release.xcconfig @@ -1,6 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_LDFLAGS = $(inherited) -ObjC +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" +OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Alamofire-watchOS" +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" $(inherited) "-D" "COCOAPODS" 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 +SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown index d8c5fed..8b3a377 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.markdown @@ -1,6 +1,29 @@ # Acknowledgements This application makes use of the following third party libraries: +## Alamofire + +Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +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. + + ## SwiftLint The MIT License (MIT) diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist index 88fb231..6a14367 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-acknowledgements.plist @@ -12,6 +12,35 @@ Type PSGroupSpecifier + + FooterText + Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +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. + + License + MIT + Title + Alamofire + Type + PSGroupSpecifier + FooterText The MIT License (MIT) diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-umbrella.h b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-umbrella.h new file mode 100644 index 0000000..9d82dbd --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension-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_SynchronyFinancial_WatchKit_ExtensionVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_SynchronyFinancial_WatchKit_ExtensionVersionString[]; + diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig index 729bac8..fb04101 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.debug.xcconfig @@ -1,6 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_LDFLAGS = $(inherited) -ObjC +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" +OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Alamofire-watchOS" +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" $(inherited) "-D" "COCOAPODS" 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 +SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.modulemap b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.modulemap new file mode 100644 index 0000000..157716f --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.modulemap @@ -0,0 +1,6 @@ +module Pods_SynchronyFinancial_WatchKit_Extension { + umbrella header "Pods-SynchronyFinancial WatchKit Extension-umbrella.h" + + export * + module * { export * } +} diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.release.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.release.xcconfig index 729bac8..fb04101 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.release.xcconfig +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial WatchKit Extension/Pods-SynchronyFinancial WatchKit Extension.release.xcconfig @@ -1,6 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_LDFLAGS = $(inherited) -ObjC +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" +OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Alamofire-watchOS" +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS/Alamofire.modulemap" $(inherited) "-D" "COCOAPODS" 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 +SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-watchOS" diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.markdown b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.markdown index d8c5fed..8b3a377 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.markdown +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.markdown @@ -1,6 +1,29 @@ # Acknowledgements This application makes use of the following third party libraries: +## Alamofire + +Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +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. + + ## SwiftLint The MIT License (MIT) diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.plist b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.plist index 88fb231..6a14367 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.plist +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-acknowledgements.plist @@ -12,6 +12,35 @@ Type PSGroupSpecifier + + FooterText + Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/) + +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. + + License + MIT + Title + Alamofire + Type + PSGroupSpecifier + FooterText The MIT License (MIT) diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-umbrella.h b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-umbrella.h new file mode 100644 index 0000000..533d8b9 --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial-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_SynchronyFinancialVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_SynchronyFinancialVersionString[]; + diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.debug.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.debug.xcconfig index 729bac8..9c1bb06 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.debug.xcconfig +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.debug.xcconfig @@ -1,6 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_LDFLAGS = $(inherited) -ObjC +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS" +OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS/Alamofire.modulemap" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Alamofire-iOS" +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS/Alamofire.modulemap" $(inherited) "-D" "COCOAPODS" 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 +SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS" diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.modulemap b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.modulemap new file mode 100644 index 0000000..02b620a --- /dev/null +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.modulemap @@ -0,0 +1,6 @@ +module Pods_SynchronyFinancial { + umbrella header "Pods-SynchronyFinancial-umbrella.h" + + export * + module * { export * } +} diff --git a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.release.xcconfig b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.release.xcconfig index 729bac8..9c1bb06 100644 --- a/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.release.xcconfig +++ b/SynchronyFinancial/Pods/Target Support Files/Pods-SynchronyFinancial/Pods-SynchronyFinancial.release.xcconfig @@ -1,6 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -OTHER_LDFLAGS = $(inherited) -ObjC +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS" +OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS/Alamofire.modulemap" +OTHER_LDFLAGS = $(inherited) -ObjC -l"Alamofire-iOS" +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS/Alamofire.modulemap" $(inherited) "-D" "COCOAPODS" 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 +SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire-iOS" diff --git a/SynchronyFinancial/podfile b/SynchronyFinancial/podfile index 6fe4c59..edd6104 100644 --- a/SynchronyFinancial/podfile +++ b/SynchronyFinancial/podfile @@ -3,14 +3,17 @@ source 'https://github.com/CocoaPods/Specs.git' target 'SynchronyFinancial' do platform :ios, '10.0' pod 'SwiftLint' + pod 'Alamofire' end target 'SynchronyFinancial WatchKit App' do platform :watchos, '2.0' pod 'SwiftLint' + pod 'Alamofire' end target 'SynchronyFinancial WatchKit Extension' do platform :watchos, '2.0' pod 'SwiftLint' + pod 'Alamofire' end