├── .gitignore
├── .swiftpm
└── xcode
│ ├── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── daniele.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ └── daniele.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── Configs
├── UAParserSwift.plist
└── UAParserSwiftTests.plist
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── UAParserSwift
│ └── UAParserSwift.swift
├── TestApplication
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Info.plist
└── ViewController.swift
├── Tests
├── .DS_Store
├── LinuxMain.swift
└── UAParserSwiftTests
│ ├── UAParserSwift_Tests.swift
│ ├── browser-test.json
│ ├── cpu-test.json
│ ├── device-test.json
│ ├── engines-test.json
│ └── os-test.json
├── UAParserSwift.podspec
├── UAParserSwift.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ └── daniele.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── xcshareddata
│ └── xcschemes
│ │ ├── UAParserSwift-iOS.xcscheme
│ │ ├── UAParserSwift-macOS.xcscheme
│ │ ├── UAParserSwift-tvOS.xcscheme
│ │ └── UAParserSwift-watchOS.xcscheme
└── xcuserdata
│ └── daniele.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ └── xcschememanagement.plist
└── banner.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcuserdata/daniele.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malcommac/UAParserSwift/a8057c7cff60db2cdf31d0a0a68ce430754ab64e/.swiftpm/xcode/package.xcworkspace/xcuserdata/daniele.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/.swiftpm/xcode/xcuserdata/daniele.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | UAParserSwift.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Configs/UAParserSwift.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSHumanReadableCopyright
24 | Copyright © 2017 Daniele Margutti. All rights reserved.
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Configs/UAParserSwiftTests.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Daniele Margutti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "UAParserSwift",
8 | platforms: [
9 | .macOS(.v10_15), .iOS(.v11)
10 | ],
11 | products: [
12 | // Products define the executables and libraries a package produces, and make them visible to other packages.
13 | .library(
14 | name: "UAParserSwift",
15 | targets: ["UAParserSwift"]),
16 | ],
17 | dependencies: [
18 | // Dependencies declare other packages that this package depends on.
19 | // .package(url: /* package url */, from: "1.0.0"),
20 | ],
21 | targets: [
22 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
23 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
24 | .target(
25 | name: "UAParserSwift",
26 | dependencies: []),
27 | .testTarget(
28 | name: "UAParserSwiftTests",
29 | dependencies: ["UAParserSwift"]),
30 | ]
31 | )
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | User-Agent Parser based upon ua-parser.js
6 |
7 | UAParserSwift is a Swift-based library to parse User Agent string; it's a port of [ua-parser-js](https://github.com/faisalman/ua-parser-js) by Faisal Salman created to be mainly used in Swift Server Side applications ([Kitura](http://kitura.io), [Vapor](https://opencollective.com/vapor) etc.).
8 | You can however use it on client side, all Apple's platforms are supported (iOS, macOS, tvOS and watchOS).
9 |
10 | This library aims to identify detailed type of web browser, layout engine, operating system, cpu architecture, and device type/model, entirely from user-agent string with a relatively small footprint.
11 |
12 | ## ❤️ Your Support
13 |
14 | *Hi fellow developer!*
15 | You know, maintaing and developing tools consumes resources and time. While I enjoy making them **your support is foundamental to allow me continue its development**.
16 |
17 | If you are using SwiftLocation or any other of my creations please consider the following options:
18 |
19 | - [**Make a donation with PayPal**](https://www.paypal.com/paypalme/danielemargutti/20)
20 | - [**Become a Sponsor**](https://github.com/sponsors/malcommac)
21 |
22 | - [Follow Me](https://github.com/malcommac)
23 |
24 | ## How it works
25 |
26 | * [Introduction](#doc)
27 | * [Supported Browsers](#browsers)
28 | * [Supported Devices](#devices)
29 | * [Supported Engines](#engines)
30 | * [Supported OSs](#oss)
31 | * [Supported Architectures](#architectures)
32 |
33 | * [Unit Tests](#tests)
34 | * [Installation](#installation)
35 | * [License](#license)
36 |
37 |
38 |
39 | ## Introduction
40 |
41 | Usage of UAParserSwift is pretty simple; just allocate an `UAParser` object along with the `User-Agent` string you want to parse.
42 |
43 | ```swift
44 | let parser = UAParser(agent: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7")
45 |
46 | // Then call properties you want to read.
47 | // Parsed data are cached and evaluated lazily in order to
48 | // get the best performances.
49 |
50 | let identified_os = parser.os
51 | let identified_device = parser.device
52 | let identified_engine = parser.engine
53 | let identified_os = parser.os
54 | let identified_cpu = parser.cpu
55 | ```
56 |
57 | Now you can call one of these properties to get parsed data (all properties are lazy created in order to keep parser lightweight):
58 |
59 | * `.browser`: return a `Browser` object with the browser's properties: `name`, `version`
60 | * `.device`: return a `Device` object with device's informations: `vendor`,`type`,`model`
61 | * `.engine`: return an `Engine` object with information about browser's engine: `name`,`version`
62 | * `.os`: return an `OS` object with the information about host operation system: `name`,`version`
63 | * `.cpu`: return a `CPU` object with the informations about host's device architecture: `identifier`
64 |
65 |
66 |
67 | ## Supported Browsers
68 |
69 | **Name**:
70 | ```
71 | Amaya, Android Browser, Arora, Avant, Baidu, Blazer, Bolt, Bowser, Camino, Chimera,
72 | Chrome [WebView], Chromium, Comodo Dragon, Conkeror, Dillo, Dolphin, Doris, Edge,
73 | Epiphany, Fennec, Firebird, Firefox, Flock, GoBrowser, iCab, ICE Browser, IceApe,
74 | IceCat, IceDragon, Iceweasel, IE[Mobile], Iron, Jasmine, K-Meleon, Konqueror, Kindle,
75 | Links, Lunascape, Lynx, Maemo, Maxthon, Midori, Minimo, MIUI Browser, [Mobile] Safari,
76 | Mosaic, Mozilla, Netfront, Netscape, NetSurf, Nokia, OmniWeb, Opera [Mini/Mobi/Tablet],
77 | PhantomJS, Phoenix, Polaris, QQBrowser, RockMelt, Silk, Skyfire, SeaMonkey, Sleipnir,
78 | SlimBrowser, Swiftfox, Tizen, UCBrowser, Vivaldi, w3m, WeChat, Yandex
79 | ```
80 |
81 | **Version**:
82 | Determined dynamically
83 |
84 |
85 |
86 | ## Supported Devices
87 |
88 | **Type**:
89 |
90 | ```
91 | console, mobile, tablet, smarttv, wearable, embedded
92 | ```
93 |
94 | **Vendor**:
95 |
96 | ```
97 | Acer, Alcatel, Amazon, Apple, Archos, Asus, BenQ, BlackBerry, Dell, GeeksPhone,
98 | Google, HP, HTC, Huawei, Jolla, Lenovo, LG, Meizu, Microsoft, Motorola, Nexian,
99 | Nintendo, Nokia, Nvidia, OnePlus, Ouya, Palm, Panasonic, Pebble, Polytron, RIM,
100 | Samsung, Sharp, Siemens, Sony[Ericsson], Sprint, Xbox, Xiaomi, ZTE
101 | ```
102 |
103 | **Model**:
104 | Determined dinamically
105 |
106 |
107 |
108 | ## Supported Engines
109 |
110 | **Engine**:
111 |
112 | ```
113 | Amaya, EdgeHTML, Gecko, iCab, KHTML, Links, Lynx, NetFront, NetSurf, Presto,
114 | Tasman, Trident, w3m, WebKit
115 | ```
116 |
117 | **Engine Version**:
118 | Determined dinamically
119 |
120 |
121 |
122 | ## Supported OSs
123 |
124 | **Name**:
125 | ```
126 | AIX, Amiga OS, Android, Arch, Bada, BeOS, BlackBerry, CentOS, Chromium OS, Contiki,
127 | Fedora, Firefox OS, FreeBSD, Debian, DragonFly, Gentoo, GNU, Haiku, Hurd, iOS,
128 | Joli, Linpus, Linux, Mac OS, Mageia, Mandriva, MeeGo, Minix, Mint, Morph OS, NetBSD,
129 | Nintendo, OpenBSD, OpenVMS, OS/2, Palm, PC-BSD, PCLinuxOS, Plan9, Playstation, QNX, RedHat,
130 | RIM Tablet OS, RISC OS, Sailfish, Series40, Slackware, Solaris, SUSE, Symbian, Tizen,
131 | Ubuntu, UNIX, VectorLinux, WebOS, Windows [Phone/Mobile], Zenwalk
132 | ```
133 |
134 | **Version**:
135 | Determined dinamically
136 |
137 |
138 |
139 | ## Supported Architectures
140 |
141 | **Identifier**:
142 | ```
143 | 68k, amd64, arm[64], avr, ia[32/64], irix[64], mips[64], pa-risc, ppc, sparc[64]
144 | ```
145 |
146 |
147 |
148 | ## Unit Tests
149 |
150 | Unit Tests are available under the [`Tests`](https://github.com/malcommac/UAParserSwift/tree/master/Tests) directory; actually they are the same tests available for ua-parser-js and all are passed successfully.
151 |
152 |
153 |
154 | ## Installation
155 |
156 | This library is written for Swift 4.x.
157 |
158 | ### Swift Package Manager (Vapor or any server side framework)
159 |
160 | Meow requires Swift 4.0 or greater to work.
161 | This is the official way to install packages for Swift Server Side.
162 | In your Package.swift, add the following to your dependencies array:
163 |
164 | ```swift
165 | .package(url: "https://github.com/malcommac/UAParserSwift.git", from: "1.0.1")
166 | ```
167 |
168 | To your target, add the "UAParserSwift" dependency.
169 |
170 | ```swift
171 | .target(name: "Application", dependencies: ["UAParserSwift", ...])
172 | ```
173 |
174 | ### CocoaPods
175 |
176 | 1. Add the pod `UAParserSwift` to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html).
177 |
178 | ```ruby
179 | pod 'UAParserSwift'
180 | ```
181 | Run `pod install` from Terminal, then open your app's `.xcworkspace` file to launch Xcode.
182 |
183 |
184 |
185 | ## Contributing
186 |
187 | - If you **need help** or you'd like to **ask a general question**, open an issue.
188 | - If you **found a bug**, open an issue.
189 | - If you **have a feature request**, open an issue.
190 | - If you **want to contribute**, submit a pull request.
191 |
192 |
193 |
194 | ## License
195 |
196 | Dual licensed under GPLv2 & MIT
197 |
198 | Copyright © 2017 Daniele Margutti
199 | Original [ua-parser-js](http://faisalman.github.io/ua-parser-js) Copyright: Copyright © 2012-2016 Faisal Salman
200 |
201 | 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:
202 |
203 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
204 |
205 | This software is licensed under [MIT License](LICENSE.md).
206 |
207 | **Consider ❤️ [support the development](#support) of this library!**
208 |
209 | ***Follow me on:***
210 | - 💼 [Linkedin](https://www.linkedin.com/in/danielemargutti/)
211 | - 🐦 [Twitter](https://twitter.com/danielemargutti)
212 |
--------------------------------------------------------------------------------
/Sources/UAParserSwift/UAParserSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UAParserSwift
3 | // Lightweight Swift-based User-Agent string parser
4 | //
5 | // ---------------------------------------------------
6 | // Created by Daniele Margutti
7 | // web: http://www.danielemargutti.com
8 | // email: hello@danielemargutti.com
9 | //
10 | // Copyright © 2017 Daniele Margutti.
11 | // Dual licensed under GPLv2 & MIT
12 | //
13 | // This is a port of ua-parser.js library in Swift
14 | // Original JavaScript Version - Copyright © 2012-2016 Faisal Salman
15 | //
16 | // Permission is hereby granted, free of charge, to any person obtaining a copy
17 | // of this software and associated documentation files (the "Software"), to deal
18 | // in the Software without restriction, including without limitation the rights
19 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20 | // copies of the Software, and to permit persons to whom the Software is
21 | // furnished to do so, subject to the following conditions:
22 | //
23 | // The above copyright notice and this permission notice shall be included in
24 | // all copies or substantial portions of the Software.
25 | //
26 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 | // THE SOFTWARE.
33 |
34 | import Foundation
35 |
36 | /// MARK: - Parser Class
37 |
38 | public class UAParser {
39 |
40 | /// User agent raw string
41 | public private(set) var agent: String
42 |
43 | /// Initialize with user agent string
44 | ///
45 | /// - Parameter agent: user agent string
46 | public init(agent: String) {
47 | self.agent = agent
48 | }
49 |
50 | /// identified browser
51 | public lazy var browser: Browser? = {
52 | return Browser(self.parse(using: Regexes.browsers))
53 | }()
54 |
55 | /// identified CPU
56 | public lazy var cpu: CPU? = {
57 | return CPU(self.parse(using: Regexes.cpu))
58 | }()
59 |
60 | /// identified device
61 | public lazy var device: Device? = {
62 | return Device(self.parse(using: Regexes.device))
63 | }()
64 |
65 | /// identified browser engine
66 | public lazy var engine: Engine? = {
67 | return Engine(self.parse(using: Regexes.engine))
68 | }()
69 |
70 | /// identified operating system
71 | public lazy var os: OS? = {
72 | return OS(self.parse(using: Regexes.os))
73 | }()
74 |
75 | /// Execute parsing based upon passed regular expressions
76 | ///
77 | /// - Parameter rules: rules to validate, the first one which pass validate the set
78 | /// - Returns: return found sets
79 | private func parse(using rules: [Rule]) -> ResultDictionary? {
80 | for rule in rules {
81 | for regex in rule.regexp {
82 | guard let matches = self.agent.matchingStrings(regex: regex) else { continue }
83 | return self.map(results: matches, to: rule.funcs)
84 | }
85 | }
86 | return nil
87 | }
88 |
89 | /// Execute mapping functions for given regula expression into the array of matched strings
90 | ///
91 | /// - Parameters:
92 | /// - results: matched strings array
93 | /// - functions: functions to execute
94 | /// - Returns: parsed data array
95 | private func map(results: [String], to functions: [Funcs]) -> ResultDictionary? {
96 | var data : ResultDictionary = [:]
97 | functions.enumerated().forEach { (idx,function) in
98 | let element: String? = (idx < results.count ? results[idx] : nil)
99 | switch function {
100 | case .r(let key):
101 | if element?.count ?? 0 > 0 {
102 | data[key] = element!.trimmingCharacters(in: .whitespacesAndNewlines)
103 | }
104 | case .rf(let key, let value):
105 | data[key] = value
106 | case .mp(let key, let mapping):
107 | guard let value = element?.uppercased() else {
108 | break
109 | }
110 | for item in mapping.map {
111 | for candidate in item.value {
112 | if value.range(of: candidate, options: .caseInsensitive) != nil {
113 | data[key] = item.key.trimmingCharacters(in: .whitespacesAndNewlines)
114 | break
115 | }
116 | }
117 | if data[key] != nil { break }
118 | }
119 | if data[key] == nil && element?.count ?? 0 > 0 {
120 | data[key] = element!
121 | }
122 | case .rp(let key, let regexp, let replaceWith):
123 | let newValue = element!.replace(withRegex: regexp, with: replaceWith)
124 | if newValue.count > 0 {
125 | data[key] = newValue.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
126 | }
127 | break
128 | }
129 | }
130 | return (data.count > 0 ? data : nil)
131 | }
132 | }
133 |
134 | // MARK: - Internal Classes
135 |
136 | /// Define a single rule to execute
137 | internal struct Rule {
138 |
139 | /// Set of regular expressions which can validate the rule
140 | public private(set) var regexp: [NSRegularExpression]
141 |
142 | /// Function to execute to parse given regexp results in a valid dictionary
143 | public private(set) var funcs: [Funcs]
144 |
145 | /// Initialize a new rule set
146 | ///
147 | /// - Parameters:
148 | /// - regexp: regular expressions
149 | /// - funcs: function to parse matched regular expression substrings
150 | public init(_ regexp: [String], _ funcs: [Funcs]) {
151 | self.regexp = regexp.map { (regex) in
152 | try! NSRegularExpression(pattern: regex, options: [.caseInsensitive])
153 | }
154 |
155 | self.funcs = funcs
156 | }
157 |
158 | }
159 |
160 | /// Mapped Dictionary
161 | internal protocol MappedKeys {
162 | var map: [String:[String]] { get }
163 | }
164 |
165 | /// Functions available to parse data
166 | ///
167 | /// - r: assign matched substring to given key
168 | /// - rf: assign fixed value to given key
169 | /// - rp: assign matched substring by sanitizing with another regexp
170 | /// - mp: map value to dictionary and assign to key
171 | internal enum Funcs {
172 | case r(_: Key)
173 | case rf(_: Key, _: String)
174 | case rp(_: Key, _: String, _: String)
175 | case mp(_: Key, _: MappedKeys)
176 | }
177 |
178 | /// Available keys
179 | ///
180 | /// - model: model of the device
181 | /// - name: name (multiple uses)
182 | /// - vendor: vendor of the device
183 | /// - type: type (multiple uses)
184 | /// - version: version (multiple uses)
185 | /// - arch: architecture of the device
186 | public enum Key {
187 | case model
188 | case name
189 | case vendor
190 | case type
191 | case version
192 | case arch
193 | }
194 |
195 | public typealias ResultDictionary = [Key:String]
196 |
197 | // MARK: - Public Represented Objects
198 |
199 | public protocol ParsableData {
200 | init?(_ data: ResultDictionary?)
201 | }
202 |
203 | /// CPU Architecture
204 | public struct CPU: ParsableData {
205 |
206 | /// Architecture identifier
207 | public private(set) var identifier: String?
208 |
209 | public init?(_ data: ResultDictionary?) {
210 | guard let arch = data?[.arch] else { return nil }
211 | self.identifier = arch
212 | }
213 | }
214 |
215 | /// Browser Identifier
216 | public struct Browser: ParsableData {
217 |
218 | /// Browser name
219 | public private(set) var name: String?
220 |
221 | /// Browser version
222 | public private(set) var version: String?
223 |
224 | public init?(_ data: ResultDictionary?) {
225 | guard let data = data else { return nil }
226 | if data[.name] == nil && data[.version] == nil { return nil }
227 | self.name = data[.name]
228 | self.version = data[.version]
229 | }
230 | }
231 |
232 | /// Device Identifier
233 | public struct Device: ParsableData {
234 |
235 | /// Device vendor
236 | public private(set) var vendor: String?
237 |
238 | /// Device type
239 | public private(set) var type: String?
240 |
241 | /// Device model
242 | public private(set) var model: String?
243 |
244 | public init?(_ data: ResultDictionary?) {
245 | guard let data = data else { return nil }
246 | self.vendor = data[.vendor]
247 | self.type = data[.type]
248 | self.model = data[.model]
249 | if self.vendor == nil && self.type == nil && self.model == nil {
250 | return nil
251 | }
252 | }
253 | }
254 |
255 | /// Browser Engine
256 | public struct Engine: ParsableData {
257 |
258 | /// Browser version
259 | public private(set) var version: String?
260 |
261 | /// Browser name
262 | public private(set) var name: String?
263 |
264 | public init?(_ data: ResultDictionary?) {
265 | guard let data = data else { return nil }
266 | self.version = data[.version]
267 | self.name = data[.name]
268 | if self.version == nil && self.name == nil {
269 | return nil
270 | }
271 | }
272 | }
273 |
274 | /// Operating Systems
275 | public struct OS: ParsableData {
276 |
277 | /// Operating system version
278 | public private(set) var version: String?
279 |
280 | /// Operating system name
281 | public private(set) var name: String?
282 |
283 | public init?(_ data: ResultDictionary?) {
284 | guard let data = data else { return nil }
285 | self.version = data[.version]
286 | self.name = data[.name]
287 | if self.version == nil && self.name == nil {
288 | return nil
289 | }
290 | }
291 | }
292 |
293 | // MARK: All Regular Expressions
294 |
295 | internal struct Regexes {
296 |
297 | /// Browsers
298 | static let browsers: [Rule] = [
299 | Rule([
300 | "(opera\\smini)\\/([\\w\\.-]+)", // Opera Mini
301 | "(opera\\s[mobiletab]+).+version\\/([\\w\\.-]+)", // Opera Mobi/Tablet
302 | "(opera).+version\\/([\\w\\.]+)", // Opera > 9.80
303 | "(opera)[\\/\\s]+([\\w\\.]+)" // Opera < 9.80
304 | ],[.r(.name),.r(.version)]),
305 | Rule([
306 | "(opios)[\\/\\s]+([\\w\\.]+)", // Opera mini on iphone >= 8.0
307 | ], [.rf(.name,"Opera Mini"), .r(.version)]),
308 | Rule([
309 | "\\s(opr)\\/([\\w\\.]+)", // Opera Webkit
310 | ], [.rf(.name,"Opera"),.r(.version)]),
311 | Rule([
312 | // Mixed
313 | "(kindle)\\/([\\w\\.]+)", // Kindle
314 | "(lunascape|maxthon|netfront|jasmine|blazer)[\\/\\s]?([\\w\\.]+)*", // Lunascape/Maxthon/Netfront/Jasmine/Blazer
315 | // Trident based
316 | "(avant\\s|iemobile|slim|baidu)(?:browser)?[\\/\\s]?([\\w\\.]*)", // Avant/IEMobile/SlimBrowser/Baidu
317 | "(?:ms|\\()(ie)\\s([\\w\\.]+)", // Internet Explorer
318 | // Webkit/KHTML based
319 | "(rekonq)\\/([\\w\\.]+)*", // Rekonq
320 | "(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser)\\/([\\w\\.-]+)" // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser
321 | ], [.r(.name),.r(.version)]),
322 | Rule([
323 | "(trident).+rv[:\\s]([\\w\\.]+).+like\\sgecko", // IE11
324 | ], [.rf(.name,"IE"),.r(.version)]),
325 | Rule([
326 | "(edge)\\/((\\d+)?[\\w\\.]+)", // Microsoft Edge
327 | ], [.r(.name),.r(.version)]),
328 | Rule([
329 | "(yabrowser)\\/([\\w\\.]+)", // Yandex
330 | ], [.rf(.name,"Yandex"),.r(.version)]),
331 | Rule([
332 | "(puffin)\\/([\\w\\.]+)", // Puffin
333 | ], [.rf(.name,"Puffin"),.r(.version)]),
334 | Rule([
335 | "((?:[\\s\\/])uc?\\s?browser|(?:juc.+)ucweb)[\\/\\s]?([\\w\\.]+)" // UCBrowser
336 | ], [.rf(.name,"UCBrowser"),.r(.version)]),
337 | Rule([
338 | "(comodo_dragon)\\/([\\w\\.]+)", // Comodo Dragon
339 | ], [.rp(.name,"_", " "), .r(.version)]),
340 | Rule([
341 | "(micromessenger)\\/([\\w\\.]+)", // WeChat
342 | ], [.rf(.name,"WeChat"),.r(.version)]),
343 | Rule([
344 | "(QQ)\\/([\\d\\.]+)", // QQ, aka ShouQ
345 | ], [.r(.name),.r(.version)]),
346 | Rule([
347 | "m?(qqbrowser)[\\/\\s]?([\\w\\.]+)", // QQBrowser
348 | ], [.r(.name),.r(.version)]),
349 | Rule([
350 | "xiaomi\\/miuibrowser\\/([\\w\\.]+)", // MIUI Browser
351 | ], [.r(.version), .rf(.name,"MIUI Browser")]),
352 | Rule([
353 | ";fbav\\/([\\w\\.]+);", // Facebook App for iOS & Android
354 | ], [.r(.version), .rf(.name,"Facebook")]),
355 | Rule([
356 | "headlesschrome(?:\\/([\\w\\.]+)|\\s)", // Chrome Headless
357 | ], [.r(.version),.rf(.name,"Chrome Headless")]),
358 | Rule([
359 | "\\swv\\).+(chrome)\\/([\\w\\.]+)", // Chrome WebView
360 | ], [.rp(.name,"(.+)/","$1 WebView"),.r(.version)]),
361 | Rule([
362 | "((?:oculus|samsung)browser)\\/([\\w\\.]+)" // Oculus / Samsung Browser
363 | ], [.rp(.name,"(.+(?:g|us))(.+)/","$1 $2"),.r(.version)]),
364 | Rule([
365 | "android.+version\\/([\\w\\.]+)\\s+(?:mobile\\s?safari|safari)*", // Android Browser
366 | ],[.r(.version),.rf(.name,"Android Browser")]),
367 | Rule([
368 | "(chrome|omniweb|arora|[tizenoka]{5}\\s?browser)\\/v?([\\w\\.]+)", // Chrome/OmniWeb/Arora/Tizen/Nokia
369 | ],[.r(.name),.r(.version)]),
370 | Rule([
371 | "(dolfin)\\/([\\w\\.]+)", // Dolphin
372 | ], [.rf(.name,"Dolphin"),.r(.version)]),
373 | Rule([
374 | "((?:android.+)crmo|crios)\\/([\\w\\.]+)", // Chrome for Android/iOS
375 | ],[.rf(.name,"Chrome"),.r(.version)]),
376 | Rule([
377 | "(coast)\\/([\\w\\.]+)", // Opera Coast
378 | ],[.rf(.name,"Opera Coast"),.r(.version)]),
379 | Rule([
380 | "fxios\\/([\\w\\.-]+)", // Firefox for iOS
381 | ], [.r(.version),.rf(.name,"Firefox")]),
382 | Rule([
383 | "version\\/([\\w\\.]+).+?mobile\\/\\w+\\s(safari)", // Mobile Safari
384 | ], [.r(.version),.rf(.name,"Mobile Safari")]),
385 | Rule([
386 | "version\\/([\\w\\.]+).+?(mobile\\s?safari|safari)", // Safari & Safari Mobile
387 | ], [.r(.version),.r(.name)]),
388 | Rule([
389 | "webkit.+?(gsa)\\/([\\w\\.]+).+?(mobile\\s?safari|safari)(\\/[\\w\\.]+)", // Google Search Appliance on iOS
390 | ], [.rf(.name,"GSA"),.r(.version)]),
391 | Rule([
392 | "webkit.+?(mobile\\s?safari|safari)(\\/[\\w\\.]+)", // Safari < 3.0
393 | ], [.r(.name),.mp(.version, OldSafariMap())]),
394 | Rule([
395 | "(konqueror)\\/([\\w\\.]+)/i,", // Konqueror
396 | "(webkit|khtml)\\/([\\w\\.]+)",
397 | ],[.r(.name),.r(.version)]),
398 | Rule([
399 | // Gecko based
400 | "(navigator|netscape)\\/([\\w\\.-]+)", // Netscape
401 | ],[.rf(.name,"Netscape"),.r(.version)]),
402 | Rule([
403 | "(swiftfox)", // Swiftfox
404 | "(icedragon|iceweasel|camino|chimera|fennec|maemo\\sbrowser|minimo|conkeror)[\\/\\s]?([\\w\\.\\+]+)", // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
405 | "(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\\/([\\w\\.-]+)", // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
406 | "(mozilla)\\/([\\w\\.]+).+rv\\:.+gecko\\/\\d+", // Mozilla
407 | // Other
408 | "(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\\/\\s]?([\\w\\.]+)", // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir
409 | "(links)\\s\\(([\\w\\.]+)", // Links,
410 | "(gobrowser)\\/?([\\w\\.]+)*", // GoBrowser
411 | "(ice\\s?browser)\\/v?([\\w\\._]+)", // ICE Browser
412 | "(mosaic)[\\/\\s]([\\w\\.]+)", // Mosaic
413 | ], [.r(.name),.r(.version)])
414 | ]
415 |
416 | /// CPU Architectures
417 | static let cpu: [Rule] = [
418 | Rule([
419 | "(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\\)]", // AMD64
420 | ], [.rf(.arch,"amd64")]),
421 | Rule([
422 | "(ia32(?=;))" // IA32 (quicktime)
423 | ], [.r(.arch)]),
424 | Rule([
425 | "((?:i[346]|x)86)[;\\)]" // // IA32
426 | ],[.rf(.arch,"ia32")]),
427 | Rule([
428 | "windows\\s(ce|mobile);\\sppc;", // PocketPC mistakenly identified as PowerPC
429 | ],[.rf(.arch,"arm")]),
430 | Rule([
431 | "((?:ppc|powerpc)(?:64)?)(?:\\smac|;|\\))", // PowerPC
432 | ],[.rp(.arch,"ower","")]),
433 | Rule([
434 | "(sun4\\w)[;\\)]", // SPARC
435 | ],[.rf(.arch,"sparc")]),
436 | Rule([
437 | "((?:avr32|ia64(?=;))|68k(?=\\))|arm(?:64|(?=v\\d+;))|(?=atmel\\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)", // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
438 | ],[.r(.arch)])
439 | ]
440 |
441 | /// Devices
442 | static let device: [Rule] = [
443 | Rule([
444 | "\\((ipad|playbook);[\\w\\s\\);-]+(rim|apple)", // iPad/PlayBook
445 | ],[.r(.model),.r(.vendor),.rf(.type,"tablet")]),
446 | Rule([
447 | "applecoremedia\\/[\\w\\.]+ \\((ipad)/", // iPad
448 | ],[.r(.model),.rf(.vendor,"apple"),.rf(.type,"tablet")]),
449 | Rule([
450 | "(apple\\s{0,1}tv)", // Apple TV
451 | ],[.rf(.model,"apple tv"),.rf(.vendor,"apple")]),
452 | Rule([
453 | "(archos)\\s(gamepad2?)", // Archos
454 | "(hp).+(touchpad)", // HP TouchPad
455 | "(hp).+(tablet)", // HP Tablet
456 | "(kindle)\\/([\\w\\.]+)", // Kindle
457 | "\\s(nook)[\\w\\s]+build\\/(\\w+)", // Nook
458 | "(dell)\\s(strea[kpr\\s\\d]*[\\dko])", // Dell Streak
459 | ],[.r(.vendor),.r(.model),.rf(.type,"tablet")]),
460 | Rule([
461 | "(kf[A-z]+)\\sbuild\\/[\\w\\.]+.*silk\\/", // Kindle Fire HD
462 | ],[.r(.model),.rf(.vendor,"amazon"),.rf(.type,"tablet")]),
463 | Rule([
464 | "(sd|kf)[0349hijorstuw]+\\sbuild\\/[\\w\\.]+.*silk\\/", // Fire Phone
465 | ],[.mp(.model,AmazonDeviceMap()),.rf(.vendor,"amazon"),.rf(.type,"mobile")]),
466 | Rule([
467 | "\\((ip[honed|\\s\\w*]+);.+(apple)", // iPod/iPhone
468 | ],[.r(.model),.r(.vendor),.rf(.type,"mobile")]),
469 | Rule([
470 | "\\((ip[honed|\\s\\w*]+);", // iPod/iPhone
471 | ],[.r(.model),.rf(.vendor,"apple"),.rf(.type,"mobile")]),
472 | Rule([
473 | "(blackberry)[\\s-]?(\\w+)", // BlackBerry
474 | "(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\\s_-]?([\\w-]+)*", // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
475 | "(hp)\\s([\\w\\s]+\\w)", // HP iPAQ
476 | "(asus)-?(\\w+)", // Asus
477 | ],[.r(.vendor),.r(.model),.rf(.type,"mobile")]),
478 | Rule([
479 | "\\(bb10;\\s(\\w+)", // BlackBerry 10
480 | ],[.r(.model),.rf(.vendor,"BlackBerry"),.rf(.type,"mobile")]),
481 | Rule([
482 | "android.+(transfo[prime\\s]{4,10}\\s\\w+|eeepc|slider\\s\\w+|nexus 7|padfone)", // Asus Tablets
483 | ],[.r(.model),.rf(.vendor,"asus"),.rf(.type,"tablet")]),
484 | Rule([
485 | "(sony)\\s(tablet\\s[ps])\\sbuild\\/", // Sony Xperia
486 | "(sony)?(?:sgp.+)\\sbuild\\/"
487 | ], [.rf(.vendor,"sony"),.rf(.model,"xperia tablet"),.rf(.type,"tablet")]),
488 | Rule([
489 | "android.+\\s([c-g]\\d{4}|so[-l]\\w+)\\sbuild\\/" // Sony
490 | ],[.r(.model),.rf(.vendor,"sony"),.rf(.type,"mobile")]),
491 | Rule([
492 | "\\s(ouya)\\s", // Ouya
493 | "(nintendo)\\s([wids3u]+)", // Nintendo
494 | ],[.r(.vendor),.r(.model),.rf(.type,"console")]),
495 | Rule([
496 | "android.+;\\s(shield)\\sbuild", // Nvidia
497 | ], [.r(.model),.rf(.vendor,"sony"),.rf(.type,"console")]),
498 | Rule([
499 | "(playstation\\s[34portablevi]+)", // Playstation
500 | ],[.r(.model),.rf(.vendor,"sony"),.rf(.type,"console")]),
501 | Rule([
502 | "(sprint\\s(\\w+))", // Sprint Phones
503 | ],[.mp(.vendor,SprintVendorMap()), .mp(.model, SprintModelMap()), .rf(.type,"mobile")]),
504 | Rule([
505 | "(lenovo)\\s?(S(?:5000|6000)+(?:[-][\\w+]))", // Lenovo tablets
506 | ], [.r(.vendor),.r(.model),.rf(.type,"tablet")]),
507 | Rule([
508 | "(htc)[;_\\s-]+([\\w\\s]+(?=\\))|\\w+)*", // HTC
509 | "(zte)-(\\w+)*", // ZTE,
510 | "(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\\s)sony)[_\\s-]?([\\w-]+)*", // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony
511 | ], [.r(.vendor),.rp(.model,"_"," "),.rf(.type,"mobile")]),
512 | Rule([
513 | "(nexus\\s9)", // HTC Nexus 9
514 | ], [.r(.model),.rf(.vendor,"htc"),.rf(.type,"tablet")]),
515 | Rule([
516 | "d\\/huawei([\\w\\s-]+)[;\\)]", // Huawei
517 | "(nexus\\s6p)"
518 | ],[.r(.model),.rf(.vendor,"huawei"),.rf(.type,"mobile")]),
519 | Rule([
520 | "(microsoft);\\s(lumia[\\s\\w]+)", // Microsoft Lumia
521 | ],[.r(.vendor),.r(.model),.rf(.type,"mobile")]),
522 | Rule([
523 | "[\\s\\(;](xbox(?:\\sone)?)[\\s\\);]", // Microsoft Xbox
524 | ],[.r(.model),.rf(.vendor,"microsoft"),.rf(.type,"console")]),
525 | Rule([
526 | "(kin\\.[onetw]{3})", // Microsoft Kin
527 | ],[.rp(.model,"\\."," "),.rf(.vendor,"microsoft"),.rf(.type,"mobile")]),
528 | Rule([
529 | "\\s(milestone|droid(?:[2-4x]|\\s(?:bionic|x2|pro|razr))?(:?\\s4g)?)[\\w\\s]+build\\/", // Motorola
530 | "mot[\\s-]?(\\w+)*",
531 | "(XT\\d{3,4}) build\\/",
532 | "(nexus\\s6)"
533 | ],[.r(.model),.rf(.vendor,"motorola"),.rf(.type,"mobile")]),
534 | Rule([
535 | "android.+\\s(mz60\\d|xoom[\\s2]{0,2})\\sbuild\\/", // Motorola
536 | ],[.r(.model),.rf(.vendor,"motorola"),.rf(.type,"tablet")]),
537 | Rule([
538 | "hbbtv\\/\\d+\\.\\d+\\.\\d+\\s+\\([\\w\\s]*;\\s*(\\w[^;]*);([^;]*)", // HbbTV devices
539 | ],[.r(.vendor),.r(.model),.rf(.type,"smarttv")]),
540 | Rule([
541 | "hbbtv.+maple;(\\d+)",
542 | ],[.rp(.model,"^/","SmartTV"),.rf(.vendor,"samsung"),.rf(.type,"smarttv")]),
543 | Rule([
544 | "\\(dtv[\\);].+(aquos)", // Sharp
545 | ],[.r(.model),.rf(.vendor,"sharp"),.rf(.type,"smarttv")]),
546 | Rule([
547 | "android.+((sch-i[89]0\\d|shw-m380s|gt-p\\d{4}|gt-n\\d+|sgh-t8[56]9|nexus 10))", // Samsung
548 | "((SM-T\\w+))"
549 | ],[.rf(.vendor,"samsung"),.r(.model),.rf(.type,"tablet")]),
550 | Rule([
551 | "smart-tv.+(samsung)",
552 | ],[.r(.vendor),.rf(.type,"smarttv"),.r(.model)]),
553 | Rule([
554 | "((s[cgp]h-\\w+|gt-\\w+|galaxy\\snexus|sm-\\w[\\w\\d]+))",
555 | "(sam[sung]*)[\\s-]*(\\w+-?[\\w-]*)*",
556 | "sec-((sgh\\w+))"
557 | ],[.rf(.vendor,"samsung"),.r(.model),.rf(.type,"mobile")]),
558 | Rule([
559 | "sie-(\\w+)*", // Siemens
560 | ],[.r(.model),.rf(.vendor,"siemes"),.rf(.type,"mobile")]),
561 | Rule([
562 | "(maemo|nokia).*(n900|lumia\\s\\d+)", // Nokia
563 | "(nokia)[\\s_-]?([\\w-]+)*",
564 | ],[.rf(.vendor,"nokia"),.r(.model),.rf(.type,"mobile")]),
565 | Rule([
566 | "android\\s3\\.[\\s\\w;-]{10}(a\\d{3})", // Acer
567 | ],[.r(.model),.rf(.vendor,"acer"),.rf(.type,"tablet")]),
568 | Rule([
569 | "android.+([vl]k\\-?\\d{3})\\s+build", // LG Tablet
570 | ],[.r(.model),.rf(.vendor,"lg"),.rf(.type,"tablet")]),
571 | Rule([
572 | "android\\s3\\.[\\s\\w;-]{10}(lg?)-([06cv9]{3,4})", // LG Tablet
573 | ],[.rf(.vendor,"lg"),.r(.model),.rf(.type,"tablet")]),
574 | Rule([
575 | "(lg) netcast\\.tv", // LG SmartTV
576 | ],[.r(.vendor),.r(.model),.rf(.type,"smarttv")]),
577 | Rule([
578 | "(nexus\\s[45])", // LG
579 | "lg[e;\\s\\/-]+(\\w+)*",
580 | "android.+lg(\\-?[\\d\\w]+)\\s+build",
581 | ],[.r(.model),.rf(.vendor,"lg"),.rf(.type,"mobile")]),
582 | Rule([
583 | "android.+(ideatab[a-z0-9\\-\\s]+)", // Lenovo
584 | ],[.r(.model),.rf(.vendor,"lenovo"),.rf(.type,"tablet")]),
585 | Rule([
586 | "linux;.+((jolla));", // Jolla
587 | ],[.r(.vendor),.r(.model),.rf(.type,"tablet")]),
588 | Rule([
589 | "((pebble))app\\/[\\d\\.]+\\s", // Pebble
590 | ],[.r(.vendor),.r(.model),.rf(.type,"wearable")]),
591 | Rule([
592 | "android.+;\\s(oppo)\\s?([\\w\\s]+)\\sbuild", // OPPO
593 | ],[.r(.vendor),.r(.model),.rf(.type,"mobile")]),
594 | Rule([
595 | "crkey", // Google Chromecast
596 | ],[.rf(.model,"chromecast"),.rf(.vendor,"google")]),
597 | Rule([
598 | "android.+;\\s(glass)\\s\\d", // Google Glass
599 | ],[.r(.model),.rf(.vendor,"google"),.rf(.type,"wearable")]),
600 | Rule([
601 | "android.+;\\s(pixel c)\\s", // Google Pixel C
602 | ],[.r(.model),.rf(.vendor,"google"),.rf(.type,"tablet")]),
603 | Rule([
604 | "android.+;\\s(pixel xl|pixel)\\s", // Google Pixel
605 | ],[.r(.model),.rf(.vendor,"google"),.rf(.type,"mobile")]),
606 | Rule([
607 | "android.+(\\w+)\\s+build\\/hm\\1", // Xiaomi Hongmi 'numeric' models
608 | "android.+(hm[\\s\\-_]*note?[\\s_]*(?:\\d\\w)?)\\s+build", // Xiaomi Hongmi
609 | "android.+(mi[\\s\\-_]*(?:one|one[\\s_]plus|note lte)?[\\s_]*(?:\\d\\w)?)\\s+build", // Xiaomi Mi
610 | "android.+(redmi[\\s\\-_]*(?:note)?(?:[\\s_]*[\\w\\s]+)?)\\s+build", // Redmi Phones
611 | ],[.rp(.model,"_"," "), .rf(.vendor,"xiaomi"),.rf(.type,"mobile")]),
612 | Rule([
613 | "android.+(mi[\\s\\-_]*(?:pad)?(?:[\\s_]*[\\w\\s]+)?)\\s+build" // Mi Pad tablets
614 | ],[.rp(.model,"_"," "), .rf(.vendor,"xiaomi"),.rf(.type,"tablet")]),
615 | Rule([
616 | "android.+;\\s(m[1-5]\\snote)\\sbuild", // Meizu Tablet
617 | ],[.r(.model),.rf(.vendor,"meizu"),.rf(.type,"tablet")]),
618 | Rule([
619 | "android.+a000(1)\\s+build", // OnePlus
620 | ],[.r(.model),.rf(.vendor,"oneplus"),.rf(.type,"mobile")]),
621 | Rule([
622 | "android.+[;\\/]\\s*(RCT[\\d\\w]+)\\s+build", // RCA Tablets
623 | ],[.r(.model),.rf(.vendor,"rca"),.rf(.type,"tablet")]),
624 | Rule([
625 | "android.+[;\\/]\\s*(Venue[\\d\\s]*)\\s+build" // // Dell Venue Tablets
626 | ],[.r(.model),.rf(.vendor,"dell"),.rf(.type,"tablet")]),
627 | Rule([
628 | "android.+[;\\/]\\s*(Q[T|M][\\d\\w]+)\\s+build", // Verizon Tablet
629 | ],[.r(.model),.rf(.vendor,"verizon"),.rf(.type,"tablet")]),
630 | Rule([
631 | "android.+[;\\/]\\s+(Barnes[&\\s]+Noble\\s+|BN[RT])(V?.*)\\s+build", // Barnes & Noble Tablet
632 | ],[.rf(.vendor,"barnes & noble"), .r(.model),.rf(.type,"tablet")]),
633 | Rule([
634 | "android.+[;\\/]\\s+(TM\\d{3}.*\\b)\\s+build", // Barnes & Noble Tablet
635 | ],[.r(.model),.rf(.vendor,"nuvision"),.rf(.type,"tablet")]),
636 | Rule([
637 | "android.+[;\\/]\\s*(zte)?.+(k\\d{2})\\s+build", // ZTE K Series Tablet
638 | ],[.rf(.vendor,"zte"),.r(.model),.rf(.type,"tablet")]),
639 | Rule([
640 | "android.+[;\\/]\\s*(gen\\d{3})\\s+build.*49h", // Swiss GEN Mobile
641 | ],[.r(.model),.rf(.vendor,"swiss"),.rf(.type,"mobile")]),
642 | Rule([
643 | "android.+[;\\/]\\s*(zur\\d{3})\\s+build", // Swiss ZUR Tablet
644 | ],[.r(.model),.rf(.vendor,"swiss"),.rf(.type,"tablet")]),
645 | Rule([
646 | "android.+[;\\/]\\s*((Zeki)?TB.*\\b)\\s+build", // Zeki Tablets
647 | ],[.r(.model),.rf(.vendor,"zeki"),.rf(.type,"tablet")]),
648 | Rule([
649 | "(android).+[;\\/]\\s+([YR]\\d{2}x?.*)\\s+build", // Dragon Touch Tablet
650 | "android.+[;\\/]\\s+(Dragon[\\-\\s]+Touch\\s+|DT)(.+)\\s+build",
651 | ],[.rf(.vendor,"dragon touch"),.r(.model),.rf(.type,"tablet")]),
652 | Rule([
653 | "android.+[;\\/]\\s*(NS-?.+)\\s+build", // Insignia Tablets
654 | ],[.r(.model),.rf(.vendor,"insignia"),.rf(.type,"tablet")]),
655 | Rule([
656 | "android.+[;\\/]\\s*((NX|Next)-?.+)\\s+build", // NextBook Tablets
657 | ],[.r(.model),.rf(.vendor,"nextbook"),.rf(.type,"tablet")]),
658 | Rule([
659 | "android.+[;\\/]\\s*(Xtreme\\_?)?(V(1[045]|2[015]|30|40|60|7[05]|90))\\s+build", // Voice Xtreme Phones
660 | ],[.rf(.vendor,"voice"),.r(.model),.rf(.type,"mobile")]),
661 | Rule([
662 | "android.+[;\\/]\\s*(LVTEL\\-?)?(V1[12])\\s+build", // LvTel Phones
663 | ],[.rf(.vendor,"lvtel"),.r(.model),.rf(.type,"mobile")]),
664 | Rule([
665 | "android.+[;\\/]\\s*(V(100MD|700NA|7011|917G).*\\b)\\s+build" // Envizen Tablets
666 | ],[.r(.model),.rf(.vendor,"envizen"),.rf(.type,"tablet")]),
667 | Rule([
668 | "android.+[;\\/]\\s*(Le[\\s\\-]+Pan)[\\s\\-]+(.*\\b)\\s+build", // Le Pan Tablets
669 | ],[.r(.vendor),.r(.model),.rf(.type,"tablet")]),
670 | Rule([
671 | "android.+[;\\/]\\s*(Trio[\\s\\-]*.*)\\s+build", // MachSpeed Tablets
672 | ],[.r(.model),.rf(.vendor,"machspeed"),.rf(.type,"tablet")]),
673 | Rule([
674 | "android.+[;\\/]\\s*(Trinity)[\\-\\s]*(T\\d{3})\\s+build", // Trinity Tablets
675 | ],[.r(.vendor),.r(.model),.rf(.type,"tablet")]),
676 | Rule([
677 | "android.+[;\\/]\\s*TU_(1491)\\s+build", // Rotor Tablets
678 | ],[.r(.model),.rf(.vendor,"rotor"),.rf(.type,"tablet")]),
679 | Rule([
680 | "android.+(KS(.+))\\s+build", // Amazon Kindle Tablets
681 | ],[.r(.model),.rf(.vendor,"amazon"),.rf(.type,"tablet")]),
682 | Rule([
683 | "android.+(Gigaset)[\\s\\-]+(Q.+)\\s+build/i]", // Gigaset Tablets
684 | ],[.r(.vendor),.r(.model),.rf(.type,"tablet")]),
685 | Rule([
686 | "\\s(tablet|tab)[;\\/]", // Unidentifiable Tablet
687 | "\\s(mobile)(?:[;\\/]|\\ssafari)", // Unidentifiable Mobile
688 | ],[.r(.type),.r(.vendor),.r(.model)]),
689 | Rule([
690 | "(android.+)[;\\/].+build", // Generic Android Device
691 | ],[.r(.model),.rf(.vendor,"generic")])
692 | ]
693 |
694 | /// Browser Engines
695 | static let engine: [Rule] = [
696 | Rule([
697 | "windows.+\\sedge\\/([\\w\\.]+)", // EdgeHTML
698 | ],[.r(.version),.rf(.name,"EdgeHTML")]),
699 | Rule([
700 | "(presto)\\/([\\w\\.]+)", // Presto
701 | "(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\\/([\\w\\.]+)", // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
702 | "(khtml|tasman|links)[\\/\\s]\\(?([\\w\\.]+)", // KHTML/Tasman/Links
703 | "(icab)[\\/\\s]([23]\\.[\\d\\.]+)" // iCab
704 | ],[.r(.name),.r(.version)]),
705 | Rule([
706 | "rv\\:([\\w\\.]+).*(gecko)" // Gecko
707 | ],[.r(.version),.r(.name)]),
708 | ]
709 |
710 | /// Operating Systems
711 | static let os: [Rule] = [
712 | Rule([
713 | // Windows based
714 | "microsoft\\s(windows)\\s(vista|xp)", // Windows (iTunes)
715 | ],[.r(.name),.r(.version)]),
716 | Rule([
717 | "(windows)\\snt\\s6\\.2;\\s(arm)", // Windows RT
718 | "(windows\\sphone(?:\\sos)*)[\\s\\/]?([\\d\\.\\s]+\\w)*", // Windows Phone
719 | "(windows\\smobile|windows)[\\s\\/]?([ntce\\d\\.\\s]+\\w)"
720 | ],[.r(.name),.mp(.version,WindowsOSMap())]),
721 | Rule([
722 | "(win(?=3|9|n)|win\\s9x\\s)([nt\\d\\.]+)", // Windows
723 | ],[.rf(.name,"windows"),.mp(.version,WindowsOSMap())]),
724 | Rule([
725 | // Mobile/Embedded OS
726 | "\\((bb)(10);" // BlackBerry 10
727 | ],[.rf(.name,"blackberry"),.r(.version)]),
728 | Rule([
729 | "(blackberry)\\w*\\/?([\\w\\.]+)*", // Blackberry
730 | "(tizen)[\\/\\s]([\\w\\.]+)", // Tizen
731 | "(android|webos|palm\\sos|qnx|bada|rim\\stablet\\sos|meego|contiki)[\\/\\s-]?([\\w\\.]+)*", // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki
732 | "linux;.+(sailfish);" // Sailfish OS
733 | ],[.r(.name),.r(.version)]),
734 | Rule([
735 | "(symbian\\s?os|symbos|s60(?=;))[\\/\\s-]?([\\w\\.]+)*", // Symbian
736 | ],[.rf(.name,"symbian"),.r(.version)]),
737 | Rule([
738 | "\\((series40);", // Series 40
739 | ],[.r(.name)]),
740 | Rule([
741 | "mozilla.+\\(mobile;.+gecko.+firefox", // Firefox OS
742 | ],[.rf(.name,"firefox os"),.r(.version)]),
743 | Rule([
744 | // Console
745 | "(nintendo|playstation)\\s([wids34portablevu]+)", // Nintendo/Playstation
746 | // GNU/Linux based
747 | "(mint)[\\/\\s\\(]?(\\w+)*", // Mint
748 | "(mageia|vectorlinux)[;\\s]", // Mageia/VectorLinux
749 | // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
750 | // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus
751 | "(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|(?=\\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\\/\\s-]?(?!chrom)([\\w\\.-]+)*",
752 | // Hurd/Linux
753 | "(hurd|linux)\\s?([\\w\\.]+)*", // Hurd/Linux
754 | "(gnu)\\s?([\\w\\.]+)*" // GNU
755 | ],[.r(.name),.r(.version)]),
756 | Rule([
757 | "(cros)\\s[\\w]+\\s([\\w\\.]+\\w)", // Chromium OS
758 | ],[.rf(.name,"chromium os"),.r(.version)]),
759 | Rule([
760 | "(sunos)\\s?([\\w\\.]+\\d)*", // Solaris
761 | ],[.rf(.name,"solaris"),.r(.version)]),
762 | Rule([
763 | // BSD based
764 | "\\s([frentopc-]{0,4}bsd|dragonfly)\\s?([\\w\\.]+)*", // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
765 | ],[.r(.name),.r(.version)]),
766 | Rule([
767 | "(haiku)\\s(\\w+)", // Haiku
768 | ],[.r(.name),.r(.version)]),
769 | Rule([
770 | "cfnetwork\\/.+darwin",
771 | "ip[honead]+(?:.*os\\s([\\w]+)\\slike\\smac|;\\sopera)", // iOS
772 | ],[.rp(.version,"_", "."),.rf(.name,"ios")]),
773 | Rule([
774 | "(mac\\sos\\sx)\\s?([\\w\\s\\.]+\\w)*",
775 | "(macintosh|mac(?=_powerpc)\\s)" // Mac OS
776 | ],[.rf(.name,"mac os"),.rp(.version,"_",".")]),
777 | Rule([
778 | // Other
779 | "((?:open)?solaris)[\\/\\s-]?([\\w\\.]+)*", // Solaris
780 | "(aix)\\s((\\d)(?=\\.|\\)|\\s)[\\w\\.]*)*", // AIX
781 | "(plan\\s9|minix|beos|os\\/2|amigaos|morphos|risc\\sos|openvms)", // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS
782 | "(unix)\\s?([\\w\\.]+)*" // UNIX
783 | ],[.r(.name),.r(.version)])
784 | ]
785 |
786 | }
787 |
788 | // MARK: - Special Mapping Data
789 |
790 | internal struct OldSafariMap: MappedKeys {
791 | public var map: [String:[String]] = [:]
792 |
793 | init() {
794 | self.map = [
795 | "1.0" : ["/8"],
796 | "1.2" : ["/1"],
797 | "1.3" : ["/3"],
798 | "2.0" : ["/412"],
799 | "2.0.2" : ["/416"],
800 | "2.0.3" : ["/417"],
801 | "2.0.4" : ["/419"],
802 | "?" : ["/"]
803 | ]
804 | }
805 | }
806 |
807 | internal struct AmazonDeviceMap: MappedKeys {
808 | public var map: [String:[String]] = [:]
809 |
810 | init() {
811 | self.map = [
812 | "Fire Phone" : ["SD", "KF"]
813 | ]
814 | }
815 | }
816 |
817 | internal struct SprintVendorMap: MappedKeys {
818 | public var map: [String:[String]] = [:]
819 |
820 | init() {
821 | self.map = [
822 | "HTC" : ["APA"],
823 | "Sprint" : ["Sprint"]
824 | ]
825 | }
826 | }
827 |
828 | internal struct SprintModelMap: MappedKeys {
829 | public var map: [String:[String]] = [:]
830 |
831 | init() {
832 | self.map = [
833 | "Evo Shift 4G" : ["7373KT"]
834 | ]
835 | }
836 | }
837 |
838 | internal struct WindowsOSMap: MappedKeys {
839 | public var map: [String:[String]] = [:]
840 |
841 | init() {
842 | self.map = [
843 | "ME" : ["4.90"],
844 | "NT 3.11" : ["NT3.51"],
845 | "NT 4.0" : ["NT4.0"],
846 | "2000" : ["NT 5.0"],
847 | "XP" : ["NT 5.1", "NT 5.2"],
848 | "Vista" : ["NT 6.0"],
849 | "7" : ["NT 6.1"],
850 | "8" : ["NT 6.2"],
851 | "8.1" : ["NT 6.3"],
852 | "10" : ["NT 6.4", "NT 10.0"],
853 | "RT" : ["ARM"]
854 | ]
855 | }
856 | }
857 |
858 |
859 | // MARK: - String Regex Extension
860 |
861 | public extension String {
862 |
863 | /// Return all matched groups extracted from self string using passed regexp
864 | ///
865 | /// - Parameter regex: regular express used to filter
866 | /// - Returns: matching strings
867 | func matchingStrings(regex: NSRegularExpression) -> [String]? {
868 | let nsString = NSString(string: self)
869 | let results = regex.matches(in: self, options: [], range: NSMakeRange(0, nsString.length))
870 | let matches = results.map { result in
871 | (0.. 1 ? Array(first_group[1...]) : first_group
879 | }
880 |
881 | /// Replace string matching given regex with passed string
882 | ///
883 | /// - Parameters:
884 | /// - pattern: regular expression
885 | /// - replaceWith: replacing value
886 | /// - Returns: new string; if error occurs the same input string is returned
887 | func replace(withRegex pattern: String, with replaceWith: String = "") -> String {
888 | do {
889 | let regex = try NSRegularExpression(pattern: pattern, options: [.caseInsensitive])
890 | let range = NSMakeRange(0, self.count)
891 | return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replaceWith)
892 | } catch {
893 | return self
894 | }
895 | }
896 | }
897 |
--------------------------------------------------------------------------------
/TestApplication/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // TestApplication
4 | //
5 | // Created by danielemargutti on 01/11/2017.
6 | // Copyright © 2017 UAParserSwift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/TestApplication/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/TestApplication/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/TestApplication/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/TestApplication/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/TestApplication/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TestApplication
4 | //
5 | // Created by danielemargutti on 01/11/2017.
6 | // Copyright © 2017 UAParserSwift. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import UAParserSwift
11 |
12 | class ViewController: UIViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | }
17 |
18 | override func didReceiveMemoryWarning() {
19 | super.didReceiveMemoryWarning()
20 | // Dispose of any resources that can be recreated.
21 |
22 | _ = UAParser(agent: "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7")
23 | }
24 |
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/Tests/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malcommac/UAParserSwift/a8057c7cff60db2cdf31d0a0a68ce430754ab64e/Tests/.DS_Store
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import UAParserSwiftTests
3 |
4 | XCTMain([
5 | testCase(UAParserSwiftTests.allTests),
6 | ])
7 |
--------------------------------------------------------------------------------
/Tests/UAParserSwiftTests/UAParserSwift_Tests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UAParserSwiftTests.swift
3 | // UAParserSwift
4 | //
5 | // Created by Daniele Margutti on 01/11/2017.
6 | // Copyright © 2017 UAParserSwift. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XCTest
11 | import UAParserSwift
12 |
13 | public struct TestItem: Decodable {
14 | public var desc: String
15 | public var ua: String
16 | public var expect: [String: String]
17 | }
18 |
19 | class UAParserSwiftTests: XCTestCase {
20 |
21 | func loadFile(named: String) -> [TestItem]? {
22 | guard let filePath = Bundle(for: UAParserSwiftTests.self).path(forResource: named, ofType: "json") else {
23 | return nil
24 | }
25 | do {
26 | let jsonData = try Data(contentsOf: URL(fileURLWithPath: filePath))
27 | let decoder = JSONDecoder()
28 | let data = try decoder.decode([TestItem].self, from: jsonData)
29 | return data
30 | } catch {
31 | return nil
32 | }
33 | }
34 |
35 | func test_cpu() {
36 | guard let tests = loadFile(named: "cpu-test") else {
37 | XCTFail("No tests found")
38 | return
39 | }
40 | for test in tests {
41 | let parser = UAParser(agent: test.ua)
42 | let arch_found = parser.cpu?.identifier?.lowercased()
43 | let arch_exp = test.expect["architecture"]?.lowercased()
44 | guard arch_found == arch_exp else {
45 | XCTFail("Failed to test CPU. Expected \(arch_exp ?? ""), found \(arch_found ?? "")")
46 | return
47 | }
48 | }
49 | }
50 |
51 | func test_engines() {
52 | guard let tests = loadFile(named: "engines-test") else {
53 | XCTFail("No tests found")
54 | return
55 | }
56 | for test in tests {
57 | let parser = UAParser(agent: test.ua)
58 | let engine_name_found = parser.engine?.name?.lowercased()
59 | let engine_ver_found = parser.engine?.version?.lowercased()
60 |
61 | let engine_name_exp = test.expect["name"]?.lowercased()
62 | let engine_ver_exp = test.expect["version"]?.lowercased()
63 |
64 | guard engine_name_found == engine_name_exp, engine_ver_found == engine_ver_exp else {
65 | XCTFail("Failed to test Engines. Expected \(engine_name_exp ?? ""), found \(engine_name_found ?? ""), Expected version \(engine_ver_exp ?? "") - Found \(engine_ver_found ?? "")")
66 | return
67 | }
68 | }
69 | }
70 |
71 | func test_os() {
72 | guard let tests = loadFile(named: "os-test") else {
73 | XCTFail("No tests found")
74 | return
75 | }
76 | for test in tests {
77 |
78 | let parser = UAParser(agent: test.ua)
79 | let os_name_found = parser.os?.name?.lowercased()
80 | let os_ver_found = parser.os?.version?.lowercased()
81 |
82 | let os_name_exp = test.expect["name"]?.lowercased()
83 | let os_ver_exp = test.expect["version"]?.lowercased()
84 |
85 | guard os_name_found == os_name_exp, os_ver_found == os_ver_exp else {
86 | XCTFail("Failed to test OS. Expected \(os_name_exp ?? ""), found \(os_name_found ?? ""), Expected version \(os_ver_exp ?? "") - Found \(os_ver_found ?? "")")
87 | return
88 | }
89 | }
90 | }
91 |
92 | func test_device() {
93 | guard let tests = loadFile(named: "device-test") else {
94 | XCTFail("No tests found")
95 | return
96 | }
97 | for test in tests {
98 |
99 | let parser = UAParser(agent: test.ua)
100 | let f_vendor = parser.device?.vendor?.lowercased()
101 | let f_model = parser.device?.model?.lowercased()
102 | let f_type = parser.device?.type?.lowercased()
103 |
104 | let e_vendor = test.expect["vendor"]?.lowercased()
105 | let e_model = test.expect["model"]?.lowercased()
106 | let e_type = test.expect["type"]?.lowercased()
107 |
108 | if f_vendor != e_vendor ||
109 | f_model != e_model ||
110 | f_type != e_type {
111 | XCTFail("Failed to test device")
112 | }
113 | }
114 | }
115 |
116 | func test_browser() {
117 | guard let tests = loadFile(named: "browser-test") else {
118 | XCTFail("No tests found")
119 | return
120 | }
121 | for test in tests {
122 |
123 | let parser = UAParser(agent: test.ua)
124 | let f_name = parser.browser?.name?.lowercased()
125 | let f_version = parser.browser?.version?.lowercased()
126 |
127 | let e_name = test.expect["name"]?.lowercased()
128 | let e_version = test.expect["version"]?.lowercased()
129 |
130 | if f_name != e_name ||
131 | f_version != e_version {
132 | XCTFail("Failed to test device")
133 | }
134 | }
135 | }
136 |
137 | static var allTests = [
138 | ("test_cpu", test_cpu),
139 | ("test_engines", test_engines),
140 | ("test_os", test_os),
141 | ("test_device", test_device),
142 | ("test_browser", test_browser),
143 | ]
144 | }
145 |
--------------------------------------------------------------------------------
/Tests/UAParserSwiftTests/browser-test.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "desc" : "Android Browser on Galaxy Nexus",
4 | "ua" : "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
5 | "expect" :
6 | {
7 | "name" : "Android Browser",
8 | "version" : "4.0",
9 | }
10 | },
11 | {
12 | "desc" : "Android Browser on Galaxy S3",
13 | "ua" : "Mozilla/5.0 (Linux; Android 4.4.4; en-us; SAMSUNG GT-I9300I Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36",
14 | "expect" :
15 | {
16 | "name" : "Android Browser",
17 | "version" : "1.5",
18 | }
19 | },
20 | {
21 | "desc" : "Android Browser on HTC Flyer (P510E)",
22 | "ua" : "Mozilla/5.0 (Linux; U; Android 3.2.1; ru-ru; HTC Flyer P510e Build/HTK75C) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
23 | "expect" :
24 | {
25 | "name" : "Android Browser",
26 | "version" : "4.0",
27 | }
28 | },
29 | {
30 | "desc" : "Android Browser on Huawei Honor Glory II (U9508)",
31 | "ua" : "Mozilla/5.0 (Linux; U; Android 4.0.4; ru-by; HUAWEI U9508 Build/HuaweiU9508) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 ACHEETAHI/2100050044",
32 | "expect" :
33 | {
34 | "name" : "Android Browser",
35 | "version" : "4.0",
36 | }
37 | },
38 | {
39 | "desc" : "Android Browser on Huawei P8 (H891L)",
40 | "ua" : "Mozilla/5.0 (Linux; Android 4.4.4; HUAWEI H891L Build/HuaweiH891L) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36",
41 | "expect" :
42 | {
43 | "name" : "Android Browser",
44 | "version" : "4.0",
45 | }
46 | },
47 | {
48 | "desc" : "Android Browser on Samsung S6 (SM-G925F)",
49 | "ua" : "Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-G925F Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.0 Chrome/38.0.2125.102 Mobile Safari/537.36",
50 | "expect" :
51 | {
52 | "name" : "SamsungBrowser",
53 | "version" : "3.0",
54 | }
55 | },
56 | {
57 | "desc" : "Arora",
58 | "ua" : "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-CH) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2",
59 | "expect" :
60 | {
61 | "name" : "Arora",
62 | "version" : "0.2",
63 | }
64 | },
65 | {
66 | "desc" : "Avant",
67 | "ua" : "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB5; Avant Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
68 | "expect" :
69 | {
70 | "name" : "Avant",
71 | }
72 | },
73 | {
74 | "desc" : "Baidu",
75 | "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; baidubrowser 1.x)",
76 | "expect" :
77 | {
78 | "name" : "baidu",
79 | "version" : "1.x",
80 | }
81 | },
82 | {
83 | "desc" : "Bolt",
84 | "ua" : "Mozilla/5.0 (X11; 78; CentOS; US-en) AppleWebKit/527+ (KHTML, like Gecko) Bolt/0.862 Version/3.0 Safari/523.15",
85 | "expect" :
86 | {
87 | "name" : "Bolt",
88 | "version" : "0.862",
89 | }
90 | },
91 | {
92 | "desc" : "Bowser",
93 | "ua" : "Mozilla/5.0 (iOS; like Mac OS X) AppleWebKit/536.36 (KHTML, like Gecko) not Chrome/27.0.1500.95 Mobile/10B141 Safari/537.36 Bowser/0.2.1",
94 | "expect" :
95 | {
96 | "name" : "Bowser",
97 | "version" : "0.2.1",
98 | }
99 | },
100 | {
101 | "desc" : "Camino",
102 | "ua" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en; rv:1.9.0.19) Gecko/2011091218 Camino/2.0.9 (like Firefox/3.0.19)",
103 | "expect" :
104 | {
105 | "name" : "Camino",
106 | "version" : "2.0.9",
107 | }
108 | },
109 | {
110 | "desc" : "Chimera",
111 | "ua" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; pl-PL; rv:1.0.1) Gecko/20021111 Chimera/0.6",
112 | "expect" :
113 | {
114 | "name" : "Chimera",
115 | "version" : "0.6",
116 | }
117 | },
118 | {
119 | "desc" : "Chrome",
120 | "ua" : "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
121 | "expect" :
122 | {
123 | "name" : "Chrome",
124 | "version" : "20.0.1090.0",
125 | }
126 | },
127 | {
128 | "desc" : "Chrome Headless",
129 | "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome Safari/537.36",
130 | "expect" :
131 | {
132 | "name" : "Chrome Headless",
133 | }
134 | },
135 | {
136 | "desc" : "Chrome Headless",
137 | "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/60.0.3112.113 Safari/537.36",
138 | "expect" :
139 | {
140 | "name" : "Chrome Headless",
141 | "version" : "60.0.3112.113",
142 | }
143 | },
144 | {
145 | "desc" : "Chrome WebView",
146 | "ua" : "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65 Mobile Safari/537.36",
147 | "expect" :
148 | {
149 | "name" : "Chrome",
150 | "version" : "43.0.2357.65",
151 | }
152 | },
153 | {
154 | "desc" : "Chrome on iOS",
155 | "ua" : "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3",
156 | "expect" :
157 | {
158 | "name" : "Chrome",
159 | "version" : "19.0.1084.60",
160 | }
161 | },
162 | {
163 | "desc" : "Chromium",
164 | "ua" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Ubuntu/11.10 Chromium/16.0.912.21 Chrome/16.0.912.21 Safari/535.7",
165 | "expect" :
166 | {
167 | "name" : "Chromium",
168 | "version" : "16.0.912.21",
169 | }
170 | },
171 | {
172 | "desc" : "Chrome on Android",
173 | "ua" : "Mozilla/5.0 (Linux; U; Android-4.0.3; en-us; Galaxy Nexus Build/IML74K) AppleWebKit/535.7 (KHTML, like Gecko) CrMo/16.0.912.75 Mobile Safari/535.7",
174 | "expect" :
175 | {
176 | "name" : "Chrome",
177 | "version" : "16.0.912.75",
178 | }
179 | },
180 | {
181 | "desc" : "Dillo",
182 | "ua" : "Dillo/2.2",
183 | "expect" :
184 | {
185 | "name" : "Dillo",
186 | "version" : "2.2",
187 | }
188 | },
189 | {
190 | "desc" : "Dolphin",
191 | "ua" : "Mozilla/5.0 (SCH-F859/F859DG12;U;NUCLEUS/2.1;Profile/MIDP-2.1 Configuration/CLDC-1.1;480*800;CTC/2.0) Dolfin/2.0",
192 | "expect" :
193 | {
194 | "name" : "Dolphin",
195 | "version" : "2.0",
196 | }
197 | },
198 | {
199 | "desc" : "Doris",
200 | "ua" : "Doris/1.15 [en] (Symbian)",
201 | "expect" :
202 | {
203 | "name" : "Doris",
204 | "version" : "1.15",
205 | }
206 | },
207 | {
208 | "desc" : "Epiphany",
209 | "ua" : "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko/20040628 Epiphany/1.2.6",
210 | "expect" :
211 | {
212 | "name" : "Epiphany",
213 | "version" : "1.2.6",
214 | }
215 | },
216 | {
217 | "desc" : "Facebook in-App Browser for Android",
218 | "ua" : "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/35.0.0.48.273;]",
219 | "expect" :
220 | {
221 | "name" : "Facebook",
222 | "version" : "35.0.0.48.273",
223 | }
224 | },
225 | {
226 | "desc" : "Facebook in-App Browser for iOS",
227 | "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304 [FBAN/FBIOS;FBAV/91.0.0.41.73;FBBV/57050710;FBDV/iPhone8,1;FBMD/iPhone;FBSN/iOS;FBSV/10.3.1;FBSS/2;FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBOP/5;FBRV/0])",
228 | "expect" :
229 | {
230 | "name" : "Facebook",
231 | "version" : "91.0.0.41.73",
232 | }
233 | },
234 | {
235 | "desc" : "Firebird",
236 | "ua" : "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031007 Firebird/0.7",
237 | "expect" :
238 | {
239 | "name" : "Firebird",
240 | "version" : "0.7",
241 | }
242 | },
243 | {
244 | "desc" : "Firefox",
245 | "ua" : "Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2",
246 | "expect" :
247 | {
248 | "name" : "Firefox",
249 | "version" : "15.0a2",
250 | }
251 | },
252 | {
253 | "desc" : "Fennec",
254 | "ua" : "Mozilla/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1",
255 | "expect" :
256 | {
257 | "name" : "Fennec",
258 | "version" : "1.0a1",
259 | }
260 | },
261 | {
262 | "desc" : "Flock",
263 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008100716 Firefox/3.0.3 Flock/2.0",
264 | "expect" :
265 | {
266 | "name" : "Flock",
267 | "version" : "2.0",
268 | }
269 | },
270 | {
271 | "desc" : "GoBrowser",
272 | "ua" : "Nokia5700XpressMusic/GoBrowser/1.6.91",
273 | "expect" :
274 | {
275 | "name" : "GoBrowser",
276 | "version" : "1.6.91",
277 | }
278 | },
279 | {
280 | "desc" : "IceApe",
281 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.19) Gecko/20110817 Iceape/2.0.14",
282 | "expect" :
283 | {
284 | "name" : "Iceape",
285 | "version" : "2.0.14",
286 | }
287 | },
288 | {
289 | "desc" : "IceCat",
290 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092921 IceCat/3.0.3-g1",
291 | "expect" :
292 | {
293 | "name" : "IceCat",
294 | "version" : "3.0.3-g1",
295 | }
296 | },
297 | {
298 | "desc" : "Iceweasel",
299 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.16) Gecko/2009121610 Iceweasel/3.0.6 (Debian-3.0.6-3)",
300 | "expect" :
301 | {
302 | "name" : "Iceweasel",
303 | "version" : "3.0.6",
304 | }
305 | },
306 | {
307 | "desc" : "iCab",
308 | "ua" : "iCab/2.9.5 (Macintosh; U; PPC; Mac OS X)",
309 | "expect" :
310 | {
311 | "name" : "iCab",
312 | "version" : "2.9.5",
313 | }
314 | },
315 | {
316 | "desc" : "IEMobile",
317 | "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) 320x240; VZW; Motorola-Q9c; Windows Mobile 6.1 Standard",
318 | "expect" :
319 | {
320 | "name" : "IEMobile",
321 | "version" : "7.11",
322 | }
323 | },
324 | {
325 | "desc" : "IE 11 with IE token",
326 | "ua" : "Mozilla/5.0 (IE 11.0; Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko",
327 | "expect" :
328 | {
329 | "name" : "IE",
330 | "version" : "11.0",
331 | }
332 | },
333 | {
334 | "desc" : "IE 11 without IE token",
335 | "ua" : "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko",
336 | "expect" :
337 | {
338 | "name" : "IE",
339 | "version" : "11.0",
340 | }
341 | },
342 | {
343 | "desc" : "K-Meleon",
344 | "ua" : "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.5) Gecko/20031016 K-Meleon/0.8.2",
345 | "expect" :
346 | {
347 | "name" : "K-Meleon",
348 | "version" : "0.8.2",
349 | }
350 | },
351 | {
352 | "desc" : "Kindle Browser",
353 | "ua" : "Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.5 (screen 600x800; rotate)",
354 | "expect" :
355 | {
356 | "name" : "Kindle",
357 | "version" : "2.5",
358 | }
359 | },
360 | {
361 | "desc" : "Konqueror",
362 | "ua" : "Mozilla/5.0 (compatible; Konqueror/3.5; Linux; X11; x86_64) KHTML/3.5.6 (like Gecko) (Kubuntu)",
363 | "expect" :
364 | {
365 | "name" : "KHTML",
366 | "version" : "3.5.6",
367 | }
368 | },
369 | {
370 | "desc" : "Lunascape",
371 | "ua" : "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090804 Firefox/3.5.2 Lunascape/5.1.4.5",
372 | "expect" :
373 | {
374 | "name" : "Lunascape",
375 | "version" : "5.1.4.5",
376 | }
377 | },
378 | {
379 | "desc" : "Lynx",
380 | "ua" : "Lynx/2.8.5dev.16 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b",
381 | "expect" :
382 | {
383 | "name" : "Lynx",
384 | "version" : "2.8.5dev.16",
385 | }
386 | },
387 | {
388 | "desc" : "Maemo Browser",
389 | "ua" : "Mozilla/5.0 (X11; U; Linux armv7l; ru-RU; rv:1.9.2.3pre) Gecko/20100723 Firefox/3.5 Maemo Browser 1.7.4.8 RX-51 N900",
390 | "expect" :
391 | {
392 | "name" : "Maemo Browser",
393 | "version" : "1.7.4.8",
394 | }
395 | },
396 | {
397 | "desc" : "Maxthon",
398 | "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)",
399 | "expect" :
400 | {
401 | "name" : "Maxthon",
402 | }
403 | },
404 | {
405 | "desc" : "Midori",
406 | "ua" : "Midori/0.2.2 (X11; Linux i686; U; en-us) WebKit/531.2+",
407 | "expect" :
408 | {
409 | "name" : "Midori",
410 | "version" : "0.2.2",
411 | }
412 | },
413 | {
414 | "desc" : "Minimo",
415 | "ua" : "Mozilla/5.0 (X11; U; Linux armv6l; rv 1.8.1.5pre) Gecko/20070619 Minimo/0.020",
416 | "expect" :
417 | {
418 | "name" : "Minimo",
419 | "version" : "0.020",
420 | }
421 | },
422 | {
423 | "desc" : "MIUI Browser on Xiaomi Hongmi WCDMA (HM2013023)",
424 | "ua" : "Mozilla/5.0 (Linux; U; Android 4.2.2; ru-ru; 2013023 Build/HM2013023) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 XiaoMi/MiuiBrowser/1.0",
425 | "expect" :
426 | {
427 | "name" : "MIUI Browser",
428 | "version" : "1.0",
429 | }
430 | },
431 | {
432 | "desc" : "Mobile Safari",
433 | "ua" : "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7",
434 | "expect" :
435 | {
436 | "name" : "Mobile Safari",
437 | "version" : "4.0.5",
438 | }
439 | },
440 | {
441 | "desc" : "Mosaic",
442 | "ua" : "NCSA_Mosaic/2.6 (X11; SunOS 4.1.3 sun4m)",
443 | "expect" :
444 | {
445 | "name" : "Mosaic",
446 | "version" : "2.6",
447 | }
448 | },
449 | {
450 | "desc" : "Mozilla",
451 | "ua" : "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20070606",
452 | "expect" :
453 | {
454 | "name" : "Mozilla",
455 | "version" : "5.0",
456 | }
457 | },
458 | {
459 | "desc" : "MSIE",
460 | "ua" : "Mozilla/4.0 (compatible; MSIE 5.0b1; Mac_PowerPC)",
461 | "expect" :
462 | {
463 | "name" : "IE",
464 | "version" : "5.0b1",
465 | }
466 | },
467 | {
468 | "desc" : "NetFront",
469 | "ua" : "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0",
470 | "expect" :
471 | {
472 | "name" : "NetFront",
473 | "version" : "3.0",
474 | }
475 | },
476 | {
477 | "desc" : "Netscape on Windows ME",
478 | "ua" : "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.8.1.8pre) Gecko/20071015 Firefox/2.0.0.7 Navigator/9.0",
479 | "expect" :
480 | {
481 | "name" : "Netscape",
482 | "version" : "9.0",
483 | }
484 | },
485 | {
486 | "desc" : "Netscape on Windows 2000",
487 | "ua" : "Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20050519 Netscape/8.0.1",
488 | "expect" :
489 | {
490 | "name" : "Netscape",
491 | "version" : "8.0.1",
492 | }
493 | },
494 | {
495 | "desc" : "Nokia Browser",
496 | "ua" : "Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaN8-00/025.007; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.37 Mobile Safari/533.4 3gpp-gba",
497 | "expect" :
498 | {
499 | "name" : "NokiaBrowser",
500 | "version" : "7.3.1.37",
501 | }
502 | },
503 | {
504 | "desc" : "Oculus Browser",
505 | "ua" : "Mozilla/5.0 (Linux; Android 7.0; SM-G920I Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/3.4.9 SamsungBrowser/4.0 Chrome/57.0.2987.146 Mobile VR Safari/537.36",
506 | "expect" :
507 | {
508 | "name" : "OculusBrowser",
509 | "version" : "3.4.9",
510 | }
511 | },
512 | {
513 | "desc" : "OmniWeb",
514 | "ua" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558.48",
515 | "expect" :
516 | {
517 | "name" : "OmniWeb",
518 | "version" : "558.48",
519 | }
520 | },
521 | {
522 | "desc" : "Opera > 9.80",
523 | "ua" : "Opera/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto/2.2.15 Version/10.10",
524 | "expect" :
525 | {
526 | "name" : "Opera",
527 | "version" : "10.10",
528 | }
529 | },
530 | {
531 | "desc" : "Opera < 9.80 on Windows",
532 | "ua" : "Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) Opera 6.01 [en]",
533 | "expect" :
534 | {
535 | "name" : "Opera",
536 | "version" : "6.01",
537 | }
538 | },
539 | {
540 | "desc" : "Opera < 9.80 on OSX",
541 | "ua" : "Opera/8.5 (Macintosh; PPC Mac OS X; U; en)",
542 | "expect" :
543 | {
544 | "name" : "Opera",
545 | "version" : "8.5",
546 | }
547 | },
548 | {
549 | "desc" : "Opera Mobile",
550 | "ua" : "Opera/9.80 (Android 2.3.5; Linux; Opera Mobi/ADR-1111101157; U; de) Presto/2.9.201 Version/11.50",
551 | "expect" :
552 | {
553 | "name" : "Opera Mobi",
554 | "version" : "11.50",
555 | }
556 | },
557 | {
558 | "desc" : "Opera Webkit",
559 | "ua" : "Mozilla/5.0 AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.123 Mobile Safari/537.22 OPR/14.0.1025.52315",
560 | "expect" :
561 | {
562 | "name" : "Opera",
563 | "version" : "14.0.1025.52315",
564 | }
565 | },
566 | {
567 | "desc" : "Opera Mini",
568 | "ua" : "Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.21214/19.916; U; en) Presto/2.5.25",
569 | "expect" :
570 | {
571 | "name" : "Opera Mini",
572 | "version" : "5.1.21214",
573 | }
574 | },
575 | {
576 | "desc" : "Opera Mini 8 above on iPhone",
577 | "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) OPiOS/12.1.1.98980 Mobile/13C75 Safari/9537.53",
578 | "expect" :
579 | {
580 | "name" : "Opera Mini",
581 | "version" : "12.1.1.98980",
582 | }
583 | },
584 | {
585 | "desc" : "Opera Tablet",
586 | "ua" : "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1",
587 | "expect" :
588 | {
589 | "name" : "Opera Tablet",
590 | "version" : "11.1",
591 | }
592 | },
593 | {
594 | "desc" : "Opera Coast",
595 | "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X; en) AppleWebKit/601.1.46 (KHTML, like Gecko) Coast/5.04.110603 Mobile/13F69 Safari/7534.48.3",
596 | "expect" :
597 | {
598 | "name" : "Opera Coast",
599 | "version" : "5.04.110603",
600 | }
601 | },
602 | {
603 | "desc" : "PhantomJS",
604 | "ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.2 Safari/534.34",
605 | "expect" :
606 | {
607 | "name" : "PhantomJS",
608 | "version" : "1.9.2",
609 | }
610 | },
611 | {
612 | "desc" : "Phoenix",
613 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2b) Gecko/20021029 Phoenix/0.4",
614 | "expect" :
615 | {
616 | "name" : "Phoenix",
617 | "version" : "0.4",
618 | }
619 | },
620 | {
621 | "desc" : "Polaris",
622 | "ua" : "LG-LX600 Polaris/6.0 MMP/2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1",
623 | "expect" :
624 | {
625 | "name" : "Polaris",
626 | "version" : "6.0",
627 | }
628 | },
629 | {
630 | "desc" : "QQ",
631 | "ua" : "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36",
632 | "expect" :
633 | {
634 | "name" : "QQBrowser",
635 | "version" : "7.1",
636 | }
637 | },
638 | {
639 | "desc" : "RockMelt",
640 | "ua" : "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) RockMelt/0.8.36.78 Chrome/7.0.517.44 Safari/534.7",
641 | "expect" :
642 | {
643 | "name" : "RockMelt",
644 | "version" : "0.8.36.78",
645 | }
646 | },
647 | {
648 | "desc" : "Safari",
649 | "ua" : "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8",
650 | "expect" :
651 | {
652 | "name" : "Safari",
653 | "version" : "5.0.1",
654 | }
655 | },
656 | {
657 | "desc" : "Safari < 3.0",
658 | "ua" : "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; sv-se) AppleWebKit/419 (KHTML, like Gecko) Safari/419.3",
659 | "expect" :
660 | {
661 | "name" : "Safari",
662 | "version" : "2.0.4",
663 | }
664 | },
665 | {
666 | "desc" : "Samsung Browser",
667 | "ua" : "Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG-SM-G925A Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36",
668 | "expect" :
669 | {
670 | "name" : "SamsungBrowser",
671 | "version" : "4.0",
672 | }
673 | },
674 | {
675 | "desc" : "SeaMonkey",
676 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b4pre) Gecko/20090405 SeaMonkey/2.0b1pre",
677 | "expect" :
678 | {
679 | "name" : "SeaMonkey",
680 | "version" : "2.0b1pre",
681 | }
682 | },
683 | {
684 | "desc" : "Silk Browser",
685 | "ua" : "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-84)",
686 | "expect" :
687 | {
688 | "name" : "Silk",
689 | "version" : "1.1.0-84",
690 | }
691 | },
692 | {
693 | "desc" : "Skyfire",
694 | "ua" : "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17 Skyfire/2.0",
695 | "expect" :
696 | {
697 | "name" : "Skyfire",
698 | "version" : "2.0",
699 | }
700 | },
701 | {
702 | "desc" : "SlimBrowser",
703 | "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SlimBrowser)",
704 | "expect" :
705 | {
706 | "name" : "Slim",
707 | }
708 | },
709 | {
710 | "desc" : "Swiftfox",
711 | "ua" : "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Firefox/2.0 (Swiftfox)",
712 | "expect" :
713 | {
714 | "name" : "Swiftfox",
715 | }
716 | },
717 | {
718 | "desc" : "Tizen Browser",
719 | "ua" : "Mozilla/5.0 (Linux; U; Tizen/1.0 like Android; en-us; AppleWebKit/534.46 (KHTML, like Gecko) Tizen Browser/1.0 Mobile",
720 | "expect" :
721 | {
722 | "name" : "Tizen Browser",
723 | "version" : "1.0",
724 | }
725 | },
726 | {
727 | "desc" : "UC Browser",
728 | "ua" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 UBrowser/5.6.12860.7 Safari/537.36",
729 | "expect" :
730 | {
731 | "name" : "UCBrowser",
732 | "version" : "5.6.12860.7",
733 | }
734 | },
735 | {
736 | "desc" : "UC Browser",
737 | "ua" : "Mozilla/5.0 (Linux; U; Android 6.0.1; en-US; Lenovo P2a42 Build/MMB29M) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/11.2.0.915 U3/0.8.0 Mobile Safari/534.30",
738 | "expect" :
739 | {
740 | "name" : "UCBrowser",
741 | "version" : "11.2.0.915",
742 | }
743 | },
744 | {
745 | "desc" : "UC Browser on Samsung",
746 | "ua" : "Mozilla/5.0 (Java; U; Pt-br; samsung-gt-s5620) UCBrowser8.2.1.144/69/352/UCWEB Mobile UNTRUSTED/1.0",
747 | "expect" :
748 | {
749 | "name" : "UCBrowser",
750 | "version" : "8.2.1.144",
751 | }
752 | },
753 | {
754 | "desc" : "UC Browser on Nokia",
755 | "ua" : "Mozilla/5.0 (S60V3; U; en-in; NokiaN73)/UC Browser8.4.0.159/28/351/UCWEB Mobile",
756 | "expect" :
757 | {
758 | "name" : "UCBrowser",
759 | "version" : "8.4.0.159",
760 | }
761 | },
762 | {
763 | "desc" : "UC Browser J2ME",
764 | "ua" : "UCWEB/2.0 (MIDP-2.0; U; zh-CN; HTC EVO 3D X515m) U2/1.0.0 UCBrowser/10.4.0.558 U2/1.0.0 Mobile",
765 | "expect" :
766 | {
767 | "name" : "UCBrowser",
768 | "version" : "10.4.0.558",
769 | }
770 | },
771 | {
772 | "desc" : "UC Browser J2ME 2",
773 | "ua" : "JUC (Linux; U; 2.3.5; zh-cn; GT-I9100; 480*800) UCWEB7.9.0.94/139/800",
774 | "expect" :
775 | {
776 | "name" : "UCBrowser",
777 | "version" : "7.9.0.94",
778 | }
779 | },
780 | {
781 | "desc": "WeChat on iOS",
782 | "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 MicroMessenger/6.3.6 NetType/WIFI Language/zh_CN",
783 | "expect":
784 | {
785 | "name": "WeChat",
786 | "version": "6.3.6",
787 | }
788 | },
789 | {
790 | "desc": "WeChat on Android",
791 | "ua": "Mozilla/5.0 (Linux; U; Android 5.1; zh-cn; Lenovo K50-t5 Build/LMY47D) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025478 Mobile Safari/533.1 MicroMessenger/6.3.5.50_r1573191.640 NetType/WIFI Language/zh_CN",
792 | "expect":
793 | {
794 | "name": "WeChat",
795 | "version": "6.3.5.50_r1573191.640",
796 | }
797 | },
798 | {
799 | "desc" : "Vivaldi",
800 | "ua" : "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Vivaldi/1.0.83.38 Safari/537.36",
801 | "expect" :
802 | {
803 | "name" : "Vivaldi",
804 | "version" : "1.0.83.38",
805 | }
806 | },
807 | {
808 | "desc" : "Yandex",
809 | "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.5 (KHTML, like Gecko) YaBrowser/1.0.1084.5402 Chrome/19.0.1084.5402 Safari/536.5",
810 | "expect" :
811 | {
812 | "name" : "Yandex",
813 | "version" : "1.0.1084.5402",
814 | }
815 | },
816 | {
817 | "desc" : "Puffin",
818 | "ua" : "Mozilla/5.0 (Linux; Android 6.0.1; Lenovo P2a42 Build/MMB29M; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Puffin/6.0.8.15804AP",
819 | "expect" :
820 | {
821 | "name" : "Puffin",
822 | "version" : "6.0.8.15804AP",
823 | }
824 | },
825 | {
826 | "desc" : "Microsoft Edge",
827 | "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0",
828 | "expect" :
829 | {
830 | "name" : "Edge",
831 | "version" : "12.0",
832 | }
833 | },
834 | {
835 | "desc" : "Iridium",
836 | "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Iridium/43.8 Safari/537.36 Chrome/43.0.2357.132",
837 | "expect" :
838 | {
839 | "name" : "Iridium",
840 | "version" : "43.8",
841 | }
842 | },
843 | {
844 | "desc" : "Firefox iOS",
845 | "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) FxiOS/1.1 Mobile/13B143 Safari/601.1.46",
846 | "expect" :
847 | {
848 | "name" : "Firefox",
849 | "version" : "1.1",
850 | }
851 | },
852 | {
853 | "desc" : "QQ on iOS",
854 | "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Mobile/14A456 QQ/6.5.3.410 V1_IPH_SQ_6.5.3_1_APP_A Pixel/1080 Core/UIWebView NetType/WIFI Mem/26",
855 | "expect" :
856 | {
857 | "name" : "QQ",
858 | "version" : "6.5.3.410",
859 | }
860 | },
861 | {
862 | "desc" : "QQ on Android",
863 | "ua" : "Mozilla/5.0 (Linux; Android 6.0; PRO 6 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile MQQBrowser/6.8 TBS/036824 Safari/537.36 V1_AND_SQ_6.5.8_422_YYB_D PA QQ/6.5.8.2910 NetType/WIFI WebP/0.3.0 Pixel/1080",
864 | "expect" :
865 | {
866 | "name" : "QQ",
867 | "version" : "6.5.8.2910",
868 | }
869 | },
870 | {
871 | "desc" : "GSA on iOS",
872 | "ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) GSA/30.1.161623614 Mobile/14F89 Safari/602.1",
873 | "expect" :
874 | {
875 | "name" : "GSA",
876 | "version" : "30.1.161623614",
877 | }
878 | }
879 | ]
880 |
--------------------------------------------------------------------------------
/Tests/UAParserSwiftTests/cpu-test.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "desc" : "i686",
4 | "ua" : "Mozilla\/5.0 (X11; Ubuntu; Linux i686; rv:19.0) Gecko\/20100101 Firefox\/19.0",
5 | "expect" : {
6 | "architecture" : "ia32"
7 | }
8 | },
9 | {
10 | "desc" : "i386",
11 | "ua" : "Mozilla\/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7) Gecko\/20040628 Epiphany\/1.2.6",
12 | "expect" : {
13 | "architecture" : "ia32"
14 | }
15 | },
16 | {
17 | "desc" : "x86-64",
18 | "ua" : "Opera\/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto\/2.2.15 Version\/10.10",
19 | "expect" : {
20 | "architecture" : "amd64"
21 | }
22 | },
23 | {
24 | "desc" : "win64",
25 | "ua" : "Mozilla\/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident\/6.0; .NET4.0E; .NET4.0C)",
26 | "expect" : {
27 | "architecture" : "amd64"
28 | }
29 | },
30 | {
31 | "desc" : "WOW64",
32 | "ua" : "Mozilla\/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident\/6.0)",
33 | "expect" : {
34 | "architecture" : "amd64"
35 | }
36 | },
37 | {
38 | "desc" : "ARMv6",
39 | "ua" : "Mozilla\/5.0 (X11; U; Linux armv61; en-US; rv:1.9.1b2pre) Gecko\/20081015 Fennec\/1.0a1",
40 | "expect" : {
41 | "architecture" : "arm"
42 | }
43 | },
44 | {
45 | "desc" : "Pocket PC",
46 | "ua" : "Opera\/9.7 (Windows Mobile; PPC; Opera Mobi\/35166; U; en) Presto\/2.2.1",
47 | "expect" : {
48 | "architecture" : "arm"
49 | }
50 | },
51 | {
52 | "desc" : "Mac PowerPC",
53 | "ua" : "Mozilla\/4.0 (compatible; MSIE 4.5; Mac_PowerPC)",
54 | "expect" : {
55 | "architecture" : "ppc"
56 | }
57 | },
58 | {
59 | "desc" : "Mac PowerPC",
60 | "ua" : "Mozilla\/4.0 (compatible; MSIE 5.17; Mac_PowerPC Mac OS; en)",
61 | "expect" : {
62 | "architecture" : "ppc"
63 | }
64 | },
65 | {
66 | "desc" : "Mac PowerPC",
67 | "ua" : "iCab\/2.9.5 (Macintosh; U; PPC; Mac OS X)",
68 | "expect" : {
69 | "architecture" : "ppc"
70 | }
71 | },
72 | {
73 | "desc" : "UltraSPARC",
74 | "ua" : "Mozilla\/5.0 (X11; U; SunOS sun4u; en-US; rv:1.9b5) Gecko\/2008032620 Firefox\/3.0b5",
75 | "expect" : {
76 | "architecture" : "sparc"
77 | }
78 | },
79 | {
80 | "desc" : "QuickTime",
81 | "ua" : "QuickTime\/7.5.6 (qtver=7.5.6;cpu=IA32;os=Mac 10.5.8)",
82 | "expect" : {
83 | "architecture" : "ia32"
84 | }
85 | },
86 | {
87 | "desc" : "XBMC",
88 | "ua" : "XBMC\/12.0 Git:20130127-fb595f2 (Windows NT 6.1;WOW64;Win64;x64; http:\/\/www.xbmc.org)",
89 | "expect" : {
90 | "architecture" : "amd64"
91 | }
92 | }
93 | ]
--------------------------------------------------------------------------------
/Tests/UAParserSwiftTests/device-test.json:
--------------------------------------------------------------------------------
1 | [{
2 | "desc": "Asus Nexus 7",
3 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36",
4 | "expect": {
5 | "vendor": "Asus",
6 | "model": "Nexus 7",
7 | "type": "tablet"
8 | }
9 | },
10 | {
11 | "desc": "Asus Padfone",
12 | "ua": "Mozilla/5.0 (Linux; Android 4.1.1; PadFone 2 Build/JRO03L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Safari/537.36",
13 | "expect": {
14 | "vendor": "Asus",
15 | "model": "PadFone",
16 | "type": "tablet"
17 | }
18 | },
19 | {
20 | "desc": "Desktop (IE11 with Tablet string)",
21 | "ua": "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; GWX:MANAGED; rv:11.0) like Gecko",
22 | "expect": {
23 | }
24 | },
25 | {
26 | "desc": "HTC Evo Shift 4G",
27 | "ua": "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; HTC APA7373KT Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0",
28 | "expect": {
29 | "vendor": "HTC",
30 | "model": "APA7373KT",
31 | "type": "mobile"
32 | }
33 | },
34 | {
35 | "desc": "HTC Nexus 9",
36 | "ua": "Mozilla/5.0 (Linux; Android 5.0; Nexus 9 Build/LRX21R) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Mobile Crosswalk/7.36.154.13 Safari/537.36",
37 | "expect": {
38 | "vendor": "HTC",
39 | "model": "Nexus 9",
40 | "type": "tablet"
41 | }
42 | },
43 | {
44 | "desc": "Huawei Honor",
45 | "ua": "Mozilla/5.0 (Linux; U; Android 2.3; xx-xx; U8860 Build/HuaweiU8860) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
46 | "expect": {
47 | "vendor": "Huawei",
48 | "model": "U8860",
49 | "type": "mobile"
50 | }
51 | },
52 | {
53 | "desc": "Huawei Nexus 6P",
54 | "ua": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MTC19V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Mobile Safari/537",
55 | "expect": {
56 | "vendor": "Huawei",
57 | "model": "Nexus 6P",
58 | "type": "mobile"
59 | }
60 | },
61 | {
62 | "desc": "Huawei P10",
63 | "ua": "Mozilla/5.0 (Linux; Android 7.0; VTR-L09 Build/HUAWEIVTR-L09; xx-xx) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Mobile Safari/537.36",
64 | "expect": {
65 | "vendor": "Huawei",
66 | "model": "VTR-L09",
67 | "type": "mobile"
68 | }
69 | },
70 | {
71 | "desc": "Huawei Y3II",
72 | "ua": "Mozilla/5.0 (Linux; U; Android 5.1; xx-xx; HUAWEI LUA-L03 Build/HUAWEILUA-L03) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36",
73 | "expect": {
74 | "vendor": "Huawei",
75 | "model": "LUA-L03",
76 | "type": "mobile"
77 | }
78 | },
79 | {
80 | "desc": "iPod",
81 | "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B554a Safari/9537.53",
82 | "expect": {
83 | "vendor": "Apple",
84 | "model": "iPod touch",
85 | "type": "mobile"
86 | }
87 | },
88 | {
89 | "desc": "LG Nexus 4",
90 | "ua": "Mozilla/5.0 (Linux; Android 4.2.1; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
91 | "expect": {
92 | "vendor": "LG",
93 | "model": "Nexus 4",
94 | "type": "mobile"
95 | }
96 | },
97 | {
98 | "desc": "LG Nexus 5",
99 | "ua": "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
100 | "expect": {
101 | "vendor": "LG",
102 | "model": "Nexus 5",
103 | "type": "mobile"
104 | }
105 | },
106 | {
107 | "desc": "Meizu M5 Note",
108 | "ua": "Mozilla/5.0 (Linux; Android 6.0; M5 Note Build/MRA58K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.49 Mobile MQQBrowser/6.2 TBS/043024 Safari/537.36 MicroMessenger/6.5.7.1040 NetType/WIFI Language/zh_CN",
109 | "expect": {
110 | "vendor": "Meizu",
111 | "model": "M5 Note",
112 | "type": "tablet"
113 | }
114 | },
115 | {
116 | "desc": "Microsoft Lumia 950",
117 | "ua": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586",
118 | "expect": {
119 | "vendor": "Microsoft",
120 | "model": "Lumia 950",
121 | "type": "mobile"
122 | }
123 | },
124 | {
125 | "desc": "Motorola Moto X",
126 | "ua": "Mozilla/5.0 (Linux; Android 4.4.4; XT1097 Build/KXE21.187-38) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Mobile Safari/537.36",
127 | "expect": {
128 | "vendor": "Motorola",
129 | "model": "XT1097",
130 | "type": "mobile"
131 | }
132 | },
133 | {
134 | "desc": "Motorola Nexus 6",
135 | "ua": "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.20 Mobile Safari/537.36",
136 | "expect": {
137 | "vendor": "Motorola",
138 | "model": "Nexus 6",
139 | "type": "mobile"
140 | }
141 | },
142 | {
143 | "desc": "Motorola Droid RAZR 4G",
144 | "ua": "Mozilla/5.0 (Linux; U; Android 2.3; xx-xx; DROID RAZR 4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
145 | "expect": {
146 | "vendor": "Motorola",
147 | "model": "DROID RAZR 4G",
148 | "type": "mobile"
149 | }
150 | },
151 | {
152 | "desc": "iPhone",
153 | "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
154 | "expect": {
155 | "vendor": "Apple",
156 | "model": "iPhone",
157 | "type": "mobile"
158 | }
159 | },
160 | {
161 | "desc": "Motorola Droid RAZR 4G",
162 | "ua": "Mozilla/5.0 (iPod touch; CPU iPhone OS 7_0_2 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A501 Safari/9537.53",
163 | "expect": {
164 | "vendor": "Apple",
165 | "model": "iPod touch",
166 | "type": "mobile"
167 | }
168 | },
169 | {
170 | "desc": "Moto X",
171 | "ua": "Mozilla/5.0 (Linux; U; Android 4.2; xx-xx; XT1058 Build/13.9.0Q2.X-70-GHOST-ATT_LE-2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
172 | "expect": {
173 | "vendor": "Motorola",
174 | "model": "XT1058",
175 | "type": "mobile"
176 | }
177 | },
178 | {
179 | "desc": "Nokia3xx",
180 | "ua": "Nokia303/14.87 CLDC-1.1",
181 | "expect": {
182 | "vendor": "Nokia",
183 | "model": "303",
184 | "type": "mobile"
185 | }
186 | },
187 | {
188 | "desc": "OnePlus One",
189 | "ua": "Mozilla/5.0 (Linux; Android 4.4.4; A0001 Build/KTU84Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36",
190 | "expect": {
191 | "vendor": "OnePlus",
192 | "model": "1",
193 | "type": "mobile"
194 | }
195 | },
196 | {
197 | "desc": "OPPO R7s",
198 | "ua": "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; OPPO R7s Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36",
199 | "expect": {
200 | "vendor": "OPPO",
201 | "model": "R7s",
202 | "type": "mobile"
203 | }
204 | },
205 | {
206 | "desc": "Philips SmartTV",
207 | "ua": "Opera/9.80 HbbTV/1.1.1 (; Philips; ; ; ; ) NETTV/4.0.2; en) Version/11.60",
208 | "expect": {
209 | "vendor": "Philips",
210 | "model": "",
211 | "type": "smarttv"
212 | }
213 | },
214 | {
215 | "desc": "Kindle Fire HD",
216 | "ua": "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.4 Mobile Safari/535.19 Silk-Accelerated=true",
217 | "expect": {
218 | "vendor": "Amazon",
219 | "model": "KFTT",
220 | "type": "tablet"
221 | }
222 | },
223 | {
224 | "desc": "Samsung Galaxy Note 8",
225 | "ua": "Mozilla/5.0 (Linux; Android 4.2.2; GT-N5100 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Safari/537.36",
226 | "expect": {
227 | "vendor": "Samsung",
228 | "model": "GT-N5100",
229 | "type": "tablet"
230 | }
231 | },
232 | {
233 | "desc": "Samsung SM-C5000",
234 | "ua": "Mozilla/5.0 (Linux; Android 6.0.1; SM-C5000 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.81 Mobile Safari/537.36 wkbrowser 4.1.35 3065",
235 | "expect": {
236 | "vendor": "Samsung",
237 | "model": "SM-C5000",
238 | "type": "mobile"
239 | }
240 | },
241 | {
242 | "desc": "Samsung SM-T231",
243 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T231 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36",
244 | "expect": {
245 | "vendor": "Samsung",
246 | "model": "SM-T231",
247 | "type": "tablet"
248 | }
249 | },
250 | {
251 | "desc": "Samsung SM-T700",
252 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T700 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36",
253 | "expect": {
254 | "vendor": "Samsung",
255 | "model": "SM-T700",
256 | "type": "tablet"
257 | }
258 | },
259 | {
260 | "desc": "Samsung SM-T520",
261 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-T520 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36",
262 | "expect": {
263 | "vendor": "Samsung",
264 | "model": "SM-T520",
265 | "type": "tablet"
266 | }
267 | },
268 | {
269 | "desc": "Samsung SmartTV2011",
270 | "ua": "HbbTV/1.1.1 (;;;;;) Maple;2011",
271 | "expect": {
272 | "vendor": "Samsung",
273 | "model": "2011",
274 | "type": "smarttv"
275 | }
276 | },
277 | {
278 | "desc": "Samsung SmartTV2012",
279 | "ua": "HbbTV/1.1.1 (;Samsung;SmartTV2012;;;) WebKit",
280 | "expect": {
281 | "vendor": "Samsung",
282 | "model": "SmartTV2012",
283 | "type": "smarttv"
284 | }
285 | },
286 | {
287 | "desc": "Samsung SmartTV2014",
288 | "ua": "HbbTV/1.1.1 (;Samsung;SmartTV2014;T-NT14UDEUC-1060.4;;) WebKit",
289 | "expect": {
290 | "vendor": "Samsung",
291 | "model": "SmartTV2014",
292 | "type": "smarttv"
293 | }
294 | },
295 | {
296 | "desc": "Samsung SmartTV",
297 | "ua": "Mozilla/5.0 (SMART-TV; Linux; Tizen 2.3) AppleWebkit/538.1 (KHTML, like Gecko) SamsungBrowser/1.0 TV Safari/538.1",
298 | "expect": {
299 | "vendor": "Samsung",
300 | "type": "smarttv"
301 | }
302 | },
303 | {
304 | "desc": "Sony C5303 (Xperia SP)",
305 | "ua": "Mozilla/5.0 (Linux; Android 4.3; C5303 Build/12.1.A.1.205) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.93 Mobile Safari/537.36",
306 | "expect": {
307 | "vendor": "Sony",
308 | "model": "C5303",
309 | "type": "mobile"
310 | }
311 | },
312 | {
313 | "desc": "Sony SO-02F (Xperia Z1 F)",
314 | "ua": "Mozilla/5.0 (Linux; Android 4.2.2; SO-02F Build/14.1.H.2.119) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36",
315 | "expect": {
316 | "vendor": "Sony",
317 | "model": "SO-02F",
318 | "type": "mobile"
319 | }
320 | },
321 | {
322 | "desc": "Sony D6653 (Xperia Z3)",
323 | "ua": "Mozilla/5.0 (Linux; Android 4.4; D6653 Build/23.0.A.0.376) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.141 Mobile Safari/537.36",
324 | "expect": {
325 | "vendor": "Sony",
326 | "model": "D6653",
327 | "type": "mobile"
328 | }
329 | },
330 | {
331 | "desc": "Sony Xperia SOL25 (ZL2)",
332 | "ua": "Mozilla/5.0 (Linux; U; Android 4.4; SOL25 Build/17.1.1.C.1.64) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
333 | "expect": {
334 | "vendor": "Sony",
335 | "model": "SOL25",
336 | "type": "mobile"
337 | }
338 | },
339 | {
340 | "desc": "Sony Xperia SP",
341 | "ua": "Mozilla/5.0 (Linux; Android 4.3; C5302 Build/12.1.A.1.201) AppleWebkit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36",
342 | "expect": {
343 | "vendor": "Sony",
344 | "model": "C5302",
345 | "type": "mobile"
346 | }
347 | },
348 | {
349 | "desc": "Sony SGP521 (Xperia Z2 Tablet)",
350 | "ua": "Mozilla/5.0 (Linux; Android 4.4; SGP521 Build/17.1.A.0.432) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Safari/537.36",
351 | "expect": {
352 | "vendor": "Sony",
353 | "model": "Xperia Tablet",
354 | "type": "tablet"
355 | }
356 | },
357 | {
358 | "desc": "Sony Tablet S",
359 | "ua": "Mozilla/5.0 (Linux; U; Android 3.1; Sony Tablet S Build/THMAS10000) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
360 | "expect": {
361 | "vendor": "Sony",
362 | "model": "Xperia Tablet",
363 | "type": "tablet"
364 | }
365 | },
366 | {
367 | "desc": "Sony Tablet Z LTE",
368 | "ua": "Mozilla/5.0 (Linux; U; Android 4.1; SonySGP321 Build/10.2.C.0.143) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
369 | "expect": {
370 | "vendor": "Sony",
371 | "model": "Xperia Tablet",
372 | "type": "tablet"
373 | }
374 | },
375 | {
376 | "desc": "Xiaomi 2013023",
377 | "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; en-US; 2013023 Build/HM2013023) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/10.0.1.512 U3/0.8.0 Mobile Safari/533.1",
378 | "expect": {
379 | "vendor": "Xiaomi",
380 | "model": "2013023",
381 | "type": "mobile"
382 | }
383 | },
384 | {
385 | "desc": "Xiaomi Hongmi Note 1W",
386 | "ua": "Mozilla/5.0 (Linux; U; Android 4.2.2; zh-CN; HM NOTE 1W Build/JDQ39) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.7.9.439 U3/0.8.0 Mobile Safari/533.1",
387 | "expect": {
388 | "vendor": "Xiaomi",
389 | "model": "HM NOTE 1W",
390 | "type": "mobile"
391 | }
392 | },
393 | {
394 | "desc": "Xiaomi Mi 3C",
395 | "ua": "Mozilla/5.0 (Linux; U; Android 4.3; zh-CN; MI 3C Build/JLS36C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.7.9.439 U3/0.8.0 Mobile Safari/533.1",
396 | "expect": {
397 | "vendor": "Xiaomi",
398 | "model": "MI 3C",
399 | "type": "mobile"
400 | }
401 | },
402 | {
403 | "desc": "Xiaomi Mi Note",
404 | "ua": "Mozilla/5.0 (Linux; Android 4.4.4; MI NOTE LTE Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36",
405 | "expect": {
406 | "vendor": "Xiaomi",
407 | "model": "MI NOTE LTE",
408 | "type": "mobile"
409 | }
410 | },
411 | {
412 | "desc": "Xiaomi Mi One Plus",
413 | "ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; MI-ONE Plus Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
414 | "expect": {
415 | "vendor": "Xiaomi",
416 | "model": "MI-ONE Plus",
417 | "type": "mobile"
418 | }
419 | },
420 | {
421 | "desc": "PlayStation 4",
422 | "ua": "Mozilla/5.0 (PlayStation 4 3.00) AppleWebKit/537.73 (KHTML, like Gecko)",
423 | "expect": {
424 | "vendor": "Sony",
425 | "model": "PlayStation 4",
426 | "type": "console"
427 | }
428 | },
429 | {
430 | "desc": "Galaxy Nexus",
431 | "ua": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
432 | "expect": {
433 | "vendor": "Samsung",
434 | "model": "Galaxy Nexus",
435 | "type": "mobile"
436 | }
437 | },
438 | {
439 | "desc": "Samsung Galaxy S5",
440 | "ua": "Mozilla/5.0 (Linux; Android 5.0; SM-G900F Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Mobile Safari/537.36",
441 | "expect": {
442 | "vendor": "Samsung",
443 | "model": "SM-G900F",
444 | "type": "mobile"
445 | }
446 | },
447 | {
448 | "desc": "Samsung Galaxy S6",
449 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-G920I Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36",
450 | "expect": {
451 | "vendor": "Samsung",
452 | "model": "SM-G920I",
453 | "type": "mobile"
454 | }
455 | },
456 | {
457 | "desc": "Samsung Galaxy S6 Edge",
458 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; SM-G925I Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.135 Safari/537.36",
459 | "expect": {
460 | "vendor": "Samsung",
461 | "model": "SM-G925I",
462 | "type": "mobile"
463 | }
464 | },
465 | {
466 | "desc": "Samsung Galaxy Note 5 Chrome",
467 | "ua": "Mozilla/5.0 (Linux; Android 5.1.1; SM-N920C Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.91 Mobile Safari/537.36",
468 | "expect": {
469 | "vendor": "Samsung",
470 | "model": "SM-N920C",
471 | "type": "mobile"
472 | }
473 | },
474 | {
475 | "desc": "Samsung Galaxy Note 5 Samsung Browser",
476 | "ua": "Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-N920C Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36",
477 | "expect": {
478 | "vendor": "Samsung",
479 | "model": "SM-N920C",
480 | "type": "mobile"
481 | }
482 | },
483 | {
484 | "desc": "Google Chromecast",
485 | "ua": "Mozilla/5.0 (X11; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.84 Safari/537.36 CrKey/1.22.79313",
486 | "expect": {
487 | "vendor": "Google",
488 | "model": "Chromecast"
489 | }
490 | },
491 | {
492 | "desc": "Google Pixel C",
493 | "ua": "Mozilla/5.0 (Linux; Android 7.0; Pixel C Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Safari/537.36",
494 | "expect": {
495 | "vendor": "Google",
496 | "model": "Pixel C",
497 | "type": "tablet"
498 | }
499 | },
500 | {
501 | "desc": "Google Pixel",
502 | "ua": "Mozilla/5.0 (Linux; Android 7.1; Pixel Build/NDE63V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Mobile Safari/537.36",
503 | "expect": {
504 | "vendor": "Google",
505 | "model": "Pixel",
506 | "type": "mobile"
507 | }
508 | },
509 | {
510 | "desc": "Google Pixel",
511 | "ua": "Mozilla/5.0 (Linux; Android 7.1; Pixel XL Build/NDE63X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.85 Mobile Safari/537.36",
512 | "expect": {
513 | "vendor": "Google",
514 | "model": "Pixel XL",
515 | "type": "mobile"
516 | }
517 | },
518 |
519 | {
520 | "desc": "Generic Android Device",
521 | "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; i980 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
522 | "expect": {
523 | "vendor": "generic",
524 | "model": "Android 6.0.1"
525 | }
526 | },
527 | {
528 | "desc": "LG VK Series Tablet",
529 | "ua": "Mozilla/5.0 (Linux; Android 5.0.2; VK700 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.84 Safari/537.36",
530 | "expect": {
531 | "vendor": "LG",
532 | "model": "VK700",
533 | "type": "tablet"
534 | }
535 | },
536 | {
537 | "desc": "LG LK Series Tablet",
538 | "ua": "Mozilla/5.0 (Linux; Android 5.0.1; LGLK430 Build/LRX21Y) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Safari/537.36",
539 | "expect": {
540 | "vendor": "LG",
541 | "model": "LK430",
542 | "type": "tablet"
543 | }
544 | },
545 | {
546 | "desc": "RCA Voyager III Tablet",
547 | "ua": "Mozilla/5.0 (Linux; Android 6.0.1; RCT6973W43 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
548 | "expect": {
549 | "vendor": "RCA",
550 | "model": "RCT6973W43",
551 | "type": "tablet"
552 | }
553 | },
554 | {
555 | "desc": "RCA Voyager II Tablet",
556 | "ua": "Mozilla/5.0 (Linux; Android 5.0; RCT6773W22B Build/LRX21M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
557 | "expect": {
558 | "vendor": "RCA",
559 | "model": "RCT6773W22B",
560 | "type": "tablet"
561 | }
562 | },
563 | {
564 | "desc": "Verizon Quanta Tablet",
565 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; QMV7B Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
566 | "expect": {
567 | "vendor": "Verizon",
568 | "model": "QMV7B",
569 | "type": "tablet"
570 | }
571 | },
572 | {
573 | "desc": "Verizon Ellipsis 8 Tablet",
574 | "ua": "Mozilla/5.0 (Linux; Android 5.1.1; QTAQZ3 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
575 | "expect": {
576 | "vendor": "Verizon",
577 | "model": "QTAQZ3",
578 | "type": "tablet"
579 | }
580 | },
581 | {
582 | "desc": "Verizon Ellipsis 8HD Tablet",
583 | "ua": "Mozilla/5.0 (Linux; Android 6.0.1; QTASUN1 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.81 Safari/537.36",
584 | "expect": {
585 | "vendor": "Verizon",
586 | "model": "QTASUN1",
587 | "type": "tablet"
588 | }
589 | },
590 | {
591 | "desc": "Dell Venue 8 Tablet",
592 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Venue 8 3830 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
593 | "expect": {
594 | "vendor": "Dell",
595 | "model": "Venue 8 3830",
596 | "type": "tablet"
597 | }
598 | },
599 | {
600 | "desc": "Dell Venue 7 Tablet",
601 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Venue 7 3730 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
602 | "expect": {
603 | "vendor": "Dell",
604 | "model": "Venue 7 3730",
605 | "type": "tablet"
606 | }
607 | },
608 | {
609 | "desc": "Barnes & Noble Nook HD+ Tablet",
610 | "ua": "Mozilla/5.0 (Linux; U; Android 4.1.2; en-us; Barnes & Noble Nook HD+ Build/JZO54K; CyanogenMod-10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
611 | "expect": {
612 | "vendor": "Barnes & Noble",
613 | "model": "Nook HD+",
614 | "type": "tablet"
615 | }
616 | },
617 | {
618 | "desc": "Barnes & Noble V400 Tablet",
619 | "ua": "Mozilla/5.0 (Linux; Android 4.0.4; BNTV400 Build/IMM76L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Safari/537.36",
620 | "expect": {
621 | "vendor": "Barnes & Noble",
622 | "model": "V400",
623 | "type": "tablet"
624 | }
625 | },
626 | {
627 | "desc": "NuVision TM101A540N Tablet",
628 | "ua": "Mozilla/5.0 (Linux; Android 5.1; TM101A540N Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/50.0.2661.86 Safari/537.36",
629 | "expect": {
630 | "vendor": "NuVision",
631 | "model": "TM101A540N",
632 | "type": "tablet"
633 | }
634 | },
635 | {
636 | "desc": "ZTE K Series Tablet",
637 | "ua": "Mozilla/5.0 (Linux; Android 6.0.1; K88 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
638 | "expect": {
639 | "vendor": "ZTE",
640 | "model": "K88",
641 | "type": "tablet"
642 | }
643 | },
644 | {
645 | "desc": "Swizz GEN610",
646 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; GEN610 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36",
647 | "expect": {
648 | "vendor": "Swiss",
649 | "model": "GEN610",
650 | "type": "mobile"
651 | }
652 | },
653 | {
654 | "desc": "Swizz ZUR700",
655 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; ZUR700 Build/KVT49L) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Safari/537.36",
656 | "expect": {
657 | "vendor": "Swiss",
658 | "model": "ZUR700",
659 | "type": "tablet"
660 | }
661 | },
662 | {
663 | "desc": "Zeki TB782b Tablet",
664 | "ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-US; TB782B Build/IMM76D) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/9.0.2.299 U3/0.8.0 Mobile Safari/534.31",
665 | "expect": {
666 | "vendor": "Zeki",
667 | "model": "TB782B",
668 | "type": "tablet"
669 | }
670 | },
671 | {
672 | "desc": "Dragon Touch Tablet",
673 | "ua": "Mozilla/5.0 (Linux; Android 4.0.4; DT9138B Build/IMM76D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Mobile Safari/537.36",
674 | "expect": {
675 | "vendor": "Dragon Touch",
676 | "model": "9138B",
677 | "type": "tablet"
678 | }
679 | },
680 | {
681 | "desc": "Insignia Tablet",
682 | "ua": "Mozilla/5.0 (Linux; U; Android 6.0.1; NS-P08A7100 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/56.0.2924.87 Safari/537.36",
683 | "expect": {
684 | "vendor": "Insignia",
685 | "model": "NS-P08A7100",
686 | "type": "tablet"
687 | }
688 | },
689 | {
690 | "desc": "Voice Xtreme V75",
691 | "ua": "Mozilla/5.0 (Linux; U; Android 4.2.1; en-us; V75 Build/JOP40D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
692 | "expect": {
693 | "vendor": "Voice",
694 | "model": "V75",
695 | "type": "mobile"
696 | }
697 | },
698 | {
699 | "desc": "LvTel V11",
700 | "ua": "Mozilla/5.0 (Linux; Android 5.1.1; V11 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36",
701 | "expect": {
702 | "vendor": "LvTel",
703 | "model": "V11",
704 | "type": "mobile"
705 | }
706 | },
707 | {
708 | "desc": "Envizen Tablet V100MD",
709 | "ua": "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; V100MD Build/V100MD.20130816) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
710 | "expect": {
711 | "vendor": "Envizen",
712 | "model": "V100MD",
713 | "type": "tablet"
714 | }
715 | },
716 | {
717 | "desc": "Rotor Tablet",
718 | "ua": "mozilla/5.0 (linux; android 5.0.1; tu_1491 build/lrx22c) applewebkit/537.36 (khtml, like gecko) chrome/43.0.2357.93 safari/537.36",
719 | "expect": {
720 | "vendor": "Rotor",
721 | "model": "1491",
722 | "type": "tablet"
723 | }
724 | },
725 | {
726 | "desc": "MachSpeed Tablets",
727 | "ua": "Mozilla/5.0 (Linux; Android 4.4.2; Trio 7.85 vQ Build/Trio_7.85_vQ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36",
728 | "expect": {
729 | "vendor": "MachSpeed",
730 | "model": "Trio 7.85 vQ",
731 | "type": "tablet"
732 | }
733 | },
734 | {
735 | "desc": "Trinity Tablets",
736 | "ua": "Mozilla/5.0 (Linux; Android 5.0.1; Trinity T101 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Safari/537.36",
737 | "expect": {
738 | "vendor": "Trinity",
739 | "model": "T101",
740 | "type": "tablet"
741 | }
742 | },
743 | {
744 | "desc": "NextBook Next7",
745 | "ua": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-us; Next7P12 Build/IMM76I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30",
746 | "expect": {
747 | "vendor": "NextBook",
748 | "model": "Next7P12",
749 | "type": "tablet"
750 | }
751 | },
752 | {
753 | "desc": "NextBook Tablets",
754 | "ua": "Mozilla/5.0 (Linux; Android 5.0; NXA8QC116 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
755 | "expect": {
756 | "vendor": "NextBook",
757 | "model": "NXA8QC116",
758 | "type": "tablet"
759 | }
760 | },
761 | {
762 | "desc": "Le Pan Tablets",
763 | "ua": "Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
764 | "expect": {
765 | "vendor": "Le Pan",
766 | "model": "TC802A",
767 | "type": "tablet"
768 | }
769 | },
770 | {
771 | "desc": "Le Pan Tablets",
772 | "ua": "Mozilla/5.0 (Linux; Android 4.2.2; Le Pan TC802A Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
773 | "expect": {
774 | "vendor": "Le Pan",
775 | "model": "TC802A",
776 | "type": "tablet"
777 | }
778 | },
779 | {
780 | "desc": "Amazon Kindle Fire Tablet",
781 | "ua": "Mozilla/5.0 (Linux; U; Android 4.4.3; en-us; KFSAWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.66 like Chrome/39.0.2171.93 Safari/537.36",
782 | "expect": {
783 | "vendor": "Amazon",
784 | "model": "KFSAWI",
785 | "type": "tablet"
786 | }
787 | },
788 | {
789 | "desc": "Gigaset Tablet",
790 | "ua": "Mozilla/5.0 (Linux; Android 4.2.2; Gigaset QV830 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
791 | "expect": {
792 | "vendor": "generic",
793 | "model": "Android 4.2.2"
794 | }
795 | },
796 | {
797 | "desc": "Redmi Note 3",
798 | "ua": "Mozilla/5.0 (Linux; Android 6.0.1; Redmi Note 3 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.116 Mobile Safari/537.36",
799 | "expect": {
800 | "vendor": "Xiaomi",
801 | "model": "Redmi Note 3",
802 | "type": "mobile"
803 | }
804 | },
805 | {
806 | "desc": "MI PAD 2",
807 | "ua": "Mozilla/5.0 (Linux; Android 5.1; MI PAD 2 Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Safari/537.36 [FB_IAB/FB4A;FBAV/137.0.0.24.91;]",
808 | "expect": {
809 | "vendor": "Xiaomi",
810 | "model": "MI PAD 2",
811 | "type": "tablet"
812 | }
813 | }
814 | ]
815 |
--------------------------------------------------------------------------------
/Tests/UAParserSwiftTests/engines-test.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "desc" : "EdgeHTML",
4 | "ua" : "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0",
5 | "expect" :
6 | {
7 | "name" : "EdgeHTML",
8 | "version" : "12.0"
9 | }
10 | },
11 | {
12 | "desc" : "Gecko",
13 | "ua" : "Mozilla/5.0 (X11; Linux x86_64; rv:2.0b9pre) Gecko/20110111 Firefox/4.0b9pre",
14 | "expect" :
15 | {
16 | "name" : "Gecko",
17 | "version" : "2.0b9pre"
18 | }
19 | },
20 | {
21 | "desc" : "KHTML",
22 | "ua" : "Mozilla/5.0 (compatible; Konqueror/4.5; FreeBSD) KHTML/4.5.4 (like Gecko)",
23 | "expect" :
24 | {
25 | "name" : "KHTML",
26 | "version" : "4.5.4"
27 | }
28 | },
29 | {
30 | "desc" : "NetFront",
31 | "ua" : "Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0",
32 | "expect" :
33 | {
34 | "name" : "NetFront",
35 | "version" : "3.0"
36 | }
37 | },
38 | {
39 | "desc" : "Presto",
40 | "ua" : "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1",
41 | "expect" :
42 | {
43 | "name" : "Presto",
44 | "version" : "2.8.149"
45 | }
46 | },
47 | {
48 | "desc" : "Tasman",
49 | "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; PPC Mac OS X 10.4.7; Tasman 1.0)",
50 | "expect" :
51 | {
52 | "name" : "Tasman",
53 | "version" : "1.0"
54 | }
55 | },
56 | {
57 | "desc" : "Trident",
58 | "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)",
59 | "expect" :
60 | {
61 | "name" : "Trident",
62 | "version" : "6.0"
63 | }
64 | },
65 | {
66 | "desc" : "WebKit",
67 | "ua" : "Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4",
68 | "expect" :
69 | {
70 | "name" : "WebKit",
71 | "version" : "533.19.4"
72 | }
73 | }
74 | ]
--------------------------------------------------------------------------------
/Tests/UAParserSwiftTests/os-test.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "desc" : "Windows 95",
4 | "ua" : "Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)",
5 | "expect" :
6 | {
7 | "name" : "Windows",
8 | "version" : "95"
9 | }
10 | },
11 | {
12 | "desc" : "Windows 98",
13 | "ua" : "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)",
14 | "expect" :
15 | {
16 | "name" : "Windows",
17 | "version" : "98"
18 | }
19 | },
20 | {
21 | "desc" : "Windows ME",
22 | "ua" : "Mozilla/5.0 (Windows; U; Win 9x 4.90) Gecko/20020502 CS 2000 7.0/7.0",
23 | "expect" :
24 | {
25 | "name" : "Windows",
26 | "version" : "ME"
27 | }
28 | },
29 | {
30 | "desc" : "Windows 2000",
31 | "ua" : "Mozilla/3.0 (compatible; MSIE 3.0; Windows NT 5.0)",
32 | "expect" :
33 | {
34 | "name" : "Windows",
35 | "version" : "2000"
36 | }
37 | },
38 | {
39 | "desc" : "Windows XP",
40 | "ua" : "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 5.2)",
41 | "expect" :
42 | {
43 | "name" : "Windows",
44 | "version" : "XP"
45 | }
46 | },
47 | {
48 | "desc" : "Windows Vista",
49 | "ua" : "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; fr-FR)",
50 | "expect" :
51 | {
52 | "name" : "Windows",
53 | "version" : "Vista"
54 | }
55 | },
56 | {
57 | "desc" : "Windows 7",
58 | "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
59 | "expect" :
60 | {
61 | "name" : "Windows",
62 | "version" : "7"
63 | }
64 | },
65 | {
66 | "desc" : "Windows 8",
67 | "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; Win64; x64; Trident/6.0; .NET4.0E; .NET4.0C)",
68 | "expect" :
69 | {
70 | "name" : "Windows",
71 | "version" : "8"
72 | }
73 | },
74 | {
75 | "desc" : "Windows 10",
76 | "ua" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0",
77 | "expect" :
78 | {
79 | "name" : "Windows",
80 | "version" : "10"
81 | }
82 | },
83 | {
84 | "desc" : "Windows RT",
85 | "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)",
86 | "expect" :
87 | {
88 | "name" : "Windows",
89 | "version" : "RT"
90 | }
91 | },
92 | {
93 | "desc" : "Windows CE",
94 | "ua" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)",
95 | "expect" :
96 | {
97 | "name" : "Windows",
98 | "version" : "CE"
99 | }
100 | },
101 | {
102 | "desc" : "Windows Mobile",
103 | "ua" : "Mozilla/5.0 (ZTE-E_N72/N72V1.0.0B02;U;Windows Mobile/6.1;Profile/MIDP-2.0 Configuration/CLDC-1.1;320*240;CTC/2.0) IE/6.0 (compatible; MSIE 4.01; Windows CE; PPC)/UC Browser7.7.1.88",
104 | "expect" :
105 | {
106 | "name" : "Windows Mobile",
107 | "version" : "6.1"
108 | }
109 | },
110 | {
111 | "desc" : "Windows Phone",
112 | "ua" : "Opera/9.80 (Windows Phone; Opera Mini/7.6.8/35.7518; U; ru) Presto/2.8.119 Version/11.10",
113 | "expect" :
114 | {
115 | "name" : "Windows Phone"
116 | }
117 | },
118 | {
119 | "desc" : "Windows Phone OS",
120 | "ua" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; DELL; Venue Pro)",
121 | "expect" :
122 | {
123 | "name" : "Windows Phone OS",
124 | "version" : "7.0"
125 | }
126 | },
127 | {
128 | "desc" : "Windows Phone 8",
129 | "ua" : "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; HTC; Windows Phone 8X by HTC)",
130 | "expect" :
131 | {
132 | "name" : "Windows Phone",
133 | "version" : "8.0"
134 | }
135 | },
136 | {
137 | "desc" : "BlackBerry",
138 | "ua" : "BlackBerry9300/5.0.0.912 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/378",
139 | "expect" :
140 | {
141 | "name" : "BlackBerry",
142 | "version" : "5.0.0.912"
143 | }
144 | },
145 | {
146 | "desc" : "BlackBerry 10",
147 | "ua" : "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.3+ (KHTML, like Gecko) Version/10.0.9.386 Mobile Safari/537.3+",
148 | "expect" :
149 | {
150 | "name" : "BlackBerry",
151 | "version" : "10"
152 | }
153 | },
154 | {
155 | "desc" : "Tizen",
156 | "ua" : "Mozilla/5.0 (Linux; Tizen 2.3; SAMSUNG SM-Z130H) AppleWebKit/537.3 (KHTML, like Gecko) Version/2.3 Mobile Safari/537.3",
157 | "expect" :
158 | {
159 | "name" : "Tizen",
160 | "version" : "2.3"
161 | }
162 | },
163 | {
164 | "desc" : "Android",
165 | "ua" : "Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; VM670 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko)",
166 | "expect" :
167 | {
168 | "name" : "Android",
169 | "version" : "2.2.2"
170 | }
171 | },
172 | {
173 | "desc" : "WebOS",
174 | "ua" : "",
175 | "expect" :
176 | {
177 | }
178 | },
179 | {
180 | "desc" : "Palm OS",
181 | "ua" : "",
182 | "expect" :
183 | {
184 | }
185 | },
186 | {
187 | "desc" : "QNX",
188 | "ua" : "",
189 | "expect" :
190 | {
191 | }
192 | },
193 | {
194 | "desc" : "Bada",
195 | "ua" : "",
196 | "expect" :
197 | {
198 | }
199 | },
200 | {
201 | "desc" : "RIM Tablet OS",
202 | "ua" : "",
203 | "expect" :
204 | {
205 | }
206 | },
207 | {
208 | "desc" : "MeeGo",
209 | "ua" : "",
210 | "expect" :
211 | {
212 | }
213 | },
214 | {
215 | "desc" : "Symbian",
216 | "ua" : "",
217 | "expect" :
218 | {
219 | }
220 | },
221 | {
222 | "desc" : "Firefox OS",
223 | "ua" : "Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0",
224 | "expect" :
225 | {
226 | "name" : "Firefox OS"
227 | }
228 | },
229 | {
230 | "desc" : "Nintendo",
231 | "ua" : "",
232 | "expect" :
233 | {
234 | }
235 | },
236 | {
237 | "desc" : "PlayStation",
238 | "ua" : "",
239 | "expect" :
240 | {
241 | }
242 | },
243 | {
244 | "desc" : "PlayStation 4",
245 | "ua" : "Mozilla/5.0 (PlayStation 4 3.00) AppleWebKit/537.73 (KHTML, like Gecko)",
246 | "expect" :
247 | {
248 | "name" : "PlayStation",
249 | "version" : "4"
250 | }
251 | },
252 | {
253 | "desc" : "Mint",
254 | "ua" : "",
255 | "expect" :
256 | {
257 | }
258 | },
259 | {
260 | "desc" : "Joli",
261 | "ua" : "",
262 | "expect" :
263 | {
264 | }
265 | },
266 | {
267 | "desc" : "Ubuntu",
268 | "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.22+ (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/535.22+ Ubuntu/12.04 (3.4.1-0ubuntu1) Epiphany/3.4.1",
269 | "expect" :
270 | {
271 | "name" : "Ubuntu",
272 | "version" : "12.04"
273 | }
274 | },
275 | {
276 | "desc" : "Ubuntu",
277 | "ua" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/31.0.1650.63 Chrome/31.0.1650.63 Safari/537.36",
278 | "expect" :
279 | {
280 | "name" : "Ubuntu"
281 | }
282 | },
283 | {
284 | "desc" : "Debian",
285 | "ua" : "",
286 | "expect" :
287 | {
288 | }
289 | },
290 | {
291 | "desc" : "OpenSUSE",
292 | "ua" : "",
293 | "expect" :
294 | {
295 | }
296 | },
297 | {
298 | "desc" : "Gentoo",
299 | "ua" : "",
300 | "expect" :
301 | {
302 | }
303 | },
304 | {
305 | "desc" : "Arch",
306 | "ua" : "",
307 | "expect" :
308 | {
309 | }
310 | },
311 | {
312 | "desc" : "Slackware",
313 | "ua" : "",
314 | "expect" :
315 | {
316 | }
317 | },
318 | {
319 | "desc" : "Fedora",
320 | "ua" : "",
321 | "expect" :
322 | {
323 | }
324 | },
325 | {
326 | "desc" : "Mandriva",
327 | "ua" : "",
328 | "expect" :
329 | {
330 | }
331 | },
332 | {
333 | "desc" : "CentOS",
334 | "ua" : "",
335 | "expect" :
336 | {
337 | }
338 | },
339 | {
340 | "desc" : "PCLinuxOS",
341 | "ua" : "",
342 | "expect" :
343 | {
344 | }
345 | },
346 | {
347 | "desc" : "RedHat",
348 | "ua" : "",
349 | "expect" :
350 | {
351 | }
352 | },
353 | {
354 | "desc" : "Zenwalk",
355 | "ua" : "",
356 | "expect" :
357 | {
358 | }
359 | },
360 | {
361 | "desc" : "Hurd",
362 | "ua" : "",
363 | "expect" :
364 | {
365 | }
366 | },
367 | {
368 | "desc" : "Linux",
369 | "ua" : "",
370 | "expect" :
371 | {
372 | }
373 | },
374 | {
375 | "desc" : "GNU",
376 | "ua" : "",
377 | "expect" :
378 | {
379 | }
380 | },
381 | {
382 | "desc" : "Chromium OS",
383 | "ua" : "",
384 | "expect" :
385 | {
386 | }
387 | },
388 | {
389 | "desc" : "Solaris",
390 | "ua" : "",
391 | "expect" :
392 | {
393 | }
394 | },
395 | {
396 | "desc" : "FreeBSD",
397 | "ua" : "",
398 | "expect" :
399 | {
400 | }
401 | },
402 | {
403 | "desc" : "OpenBSD",
404 | "ua" : "",
405 | "expect" :
406 | {
407 | }
408 | },
409 | {
410 | "desc" : "NetBSD",
411 | "ua" : "",
412 | "expect" :
413 | {
414 | }
415 | },
416 | {
417 | "desc" : "DragonFly",
418 | "ua" : "",
419 | "expect" :
420 | {
421 | }
422 | },
423 | {
424 | "desc" : "iOS in App",
425 | "ua" : "AppName/version CFNetwork/version Darwin/version",
426 | "expect" :
427 | {
428 | "name" : "iOS",
429 | "version" : "cfnetwork/version darwin"
430 | }
431 | },
432 | {
433 | "desc" : "iOS with Chrome",
434 | "ua" : "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3",
435 | "expect" :
436 | {
437 | "name" : "iOS",
438 | "version" : "5.1.1"
439 | }
440 | },
441 | {
442 | "desc" : "iOS with Opera Mini",
443 | "ua" : "Opera/9.80 (iPhone; Opera Mini/7.1.32694/27.1407; U; en) Presto/2.8.119 Version/11.10",
444 | "expect" :
445 | {
446 | "name" : "iOS"
447 | }
448 | },
449 | {
450 | "desc" : "Mac OS",
451 | "ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
452 | "expect" :
453 | {
454 | "name" : "Mac OS",
455 | "version" : "10.6.8"
456 | }
457 | },
458 | {
459 | "desc" : "Haiku",
460 | "ua" : "Mozilla/5.0 (Macintosh; Intel Haiku R1 x86) AppleWebKit/602.1.1 (KHTML, like Gecko) WebPositive/1.2 Version/8.0 Safari/602.1.1",
461 | "expect" :
462 | {
463 | "name" : "Haiku",
464 | "version" : "R1"
465 | }
466 | },
467 | {
468 | "desc" : "AIX",
469 | "ua" : "",
470 | "expect" :
471 | {
472 | }
473 | },
474 | {
475 | "desc" : "Plan9",
476 | "ua" : "",
477 | "expect" :
478 | {
479 | }
480 | },
481 | {
482 | "desc" : "Minix",
483 | "ua" : "",
484 | "expect" :
485 | {
486 | }
487 | },
488 | {
489 | "desc" : "BeOS",
490 | "ua" : "",
491 | "expect" :
492 | {
493 | }
494 | },
495 | {
496 | "desc" : "OS/2",
497 | "ua" : "",
498 | "expect" :
499 | {
500 | }
501 | },
502 | {
503 | "desc" : "AmigaOS",
504 | "ua" : "",
505 | "expect" :
506 | {
507 | }
508 | },
509 | {
510 | "desc" : "MorphOS",
511 | "ua" : "",
512 | "expect" :
513 | {
514 | }
515 | },
516 | {
517 | "desc" : "UNIX",
518 | "ua" : "",
519 | "expect" :
520 | {
521 | }
522 | },
523 | {
524 | "desc" : "iTunes Windows Vista",
525 | "ua" : "iTunes/10.7 (Windows; Microsoft Windows Vista Home Premium Edition Service Pack 1 (Build 6001)) AppleWebKit/536.26.9",
526 | "expect" :
527 | {
528 | "name" : "Windows",
529 | "version" : "Vista"
530 | }
531 | },
532 | {
533 | "desc" : "iOS BE App",
534 | "ua" : "APP-BE Test/1.0 (iPad; Apple; CPU iPhone OS 7_0_2 like Mac OS X)",
535 | "expect" :
536 | {
537 | "name" : "iOS",
538 | "version" : "7.0.2"
539 | }
540 | },
541 | {
542 | "desc" : "KTB-Nexus 5",
543 | "ua" : "APP-My App/1.0 (Linux; Android 4.2.1; Nexus 5 Build/JOP40D)",
544 | "expect" :
545 | {
546 | "name" : "Android",
547 | "version" : "4.2.1"
548 | }
549 | }
550 | ]
551 |
--------------------------------------------------------------------------------
/UAParserSwift.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "UAParserSwift"
3 | s.version = "1.2.1"
4 | s.summary = "User-Agent parser for swift (port of ua-parser-js)"
5 | s.description = <<-DESC
6 | UAParserSwift is a Swift-based library to parse User Agent string; it's a port of ua-parser-js by Faisal Salman created to be mainly used in Swift Server Side applications (but compatible with all Apple's platforms too).
7 | DESC
8 | s.homepage = "https://github.com/malcommac/UAParserSwift.git"
9 | s.license = { :type => "MIT", :file => "LICENSE" }
10 | s.author = { "Daniele Margutti" => "me@danielemargutti.com" }
11 | s.social_media_url = "http://twitter.com/danielemargutti"
12 | s.ios.deployment_target = "11.0"
13 | s.osx.deployment_target = "10.9"
14 | s.watchos.deployment_target = "2.0"
15 | s.tvos.deployment_target = "9.0"
16 | s.source = { :git => "https://github.com/malcommac/UAParserSwift.git", :tag => s.version.to_s }
17 | s.source_files = "Sources/**/*.swift"
18 | s.frameworks = "Foundation"
19 | s.swift_versions = ['5.0', '5.1', '5.3']
20 | end
21 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 47;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 52D6D9871BEFF229002C0205 /* UAParserSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* UAParserSwift.framework */; };
11 | 643640B51FACF6CF002C4859 /* cpu-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640B41FACF6CF002C4859 /* cpu-test.json */; };
12 | 643640B61FACF6CF002C4859 /* cpu-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640B41FACF6CF002C4859 /* cpu-test.json */; };
13 | 643640B71FACF6CF002C4859 /* cpu-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640B41FACF6CF002C4859 /* cpu-test.json */; };
14 | 643640BD1FACFB25002C4859 /* engines-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640BC1FACFB25002C4859 /* engines-test.json */; };
15 | 643640BE1FACFB25002C4859 /* engines-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640BC1FACFB25002C4859 /* engines-test.json */; };
16 | 643640BF1FACFB25002C4859 /* engines-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640BC1FACFB25002C4859 /* engines-test.json */; };
17 | 643640C11FACFE28002C4859 /* os-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C01FACFE28002C4859 /* os-test.json */; };
18 | 643640C21FACFE28002C4859 /* os-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C01FACFE28002C4859 /* os-test.json */; };
19 | 643640C31FACFE28002C4859 /* os-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C01FACFE28002C4859 /* os-test.json */; };
20 | 643640C51FADBDFC002C4859 /* device-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C41FADBDFC002C4859 /* device-test.json */; };
21 | 643640C61FADBDFC002C4859 /* device-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C41FADBDFC002C4859 /* device-test.json */; };
22 | 643640C71FADBDFC002C4859 /* device-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C41FADBDFC002C4859 /* device-test.json */; };
23 | 643640C91FADE74A002C4859 /* browser-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C81FADE74A002C4859 /* browser-test.json */; };
24 | 643640CA1FADE74A002C4859 /* browser-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C81FADE74A002C4859 /* browser-test.json */; };
25 | 643640CB1FADE74A002C4859 /* browser-test.json in Resources */ = {isa = PBXBuildFile; fileRef = 643640C81FADE74A002C4859 /* browser-test.json */; };
26 | 64C2F9FF1FAF849C00E3EEDC /* UAParserSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C2F9FE1FAF849C00E3EEDC /* UAParserSwift.swift */; };
27 | 64C2FA001FAF849C00E3EEDC /* UAParserSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C2F9FE1FAF849C00E3EEDC /* UAParserSwift.swift */; };
28 | 64C2FA011FAF849C00E3EEDC /* UAParserSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C2F9FE1FAF849C00E3EEDC /* UAParserSwift.swift */; };
29 | 64C2FA021FAF849C00E3EEDC /* UAParserSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C2F9FE1FAF849C00E3EEDC /* UAParserSwift.swift */; };
30 | 64CD6C331FAA2175009B4F9A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64CD6C321FAA2175009B4F9A /* AppDelegate.swift */; };
31 | 64CD6C351FAA2175009B4F9A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64CD6C341FAA2175009B4F9A /* ViewController.swift */; };
32 | 64CD6C381FAA2175009B4F9A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 64CD6C361FAA2175009B4F9A /* Main.storyboard */; };
33 | 64CD6C3A1FAA2175009B4F9A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 64CD6C391FAA2175009B4F9A /* Assets.xcassets */; };
34 | 64CD6C3D1FAA2175009B4F9A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 64CD6C3B1FAA2175009B4F9A /* LaunchScreen.storyboard */; };
35 | 64CD6C451FAA2181009B4F9A /* UAParserSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* UAParserSwift.framework */; };
36 | 64CD6C471FAA218E009B4F9A /* UAParserSwift.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* UAParserSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
37 | 8933C78E1EB5B82C000D00A4 /* UAParserSwift_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7891EB5B82A000D00A4 /* UAParserSwift_Tests.swift */; };
38 | 8933C78F1EB5B82C000D00A4 /* UAParserSwift_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7891EB5B82A000D00A4 /* UAParserSwift_Tests.swift */; };
39 | 8933C7901EB5B82D000D00A4 /* UAParserSwift_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7891EB5B82A000D00A4 /* UAParserSwift_Tests.swift */; };
40 | DD7502881C68FEDE006590AF /* UAParserSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6DA0F1BF000BD002C0205 /* UAParserSwift.framework */; };
41 | DD7502921C690C7A006590AF /* UAParserSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D9F01BEFFFBE002C0205 /* UAParserSwift.framework */; };
42 | /* End PBXBuildFile section */
43 |
44 | /* Begin PBXContainerItemProxy section */
45 | 52D6D9881BEFF229002C0205 /* PBXContainerItemProxy */ = {
46 | isa = PBXContainerItemProxy;
47 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
48 | proxyType = 1;
49 | remoteGlobalIDString = 52D6D97B1BEFF229002C0205;
50 | remoteInfo = UAParserSwift;
51 | };
52 | 64CD6C421FAA217B009B4F9A /* PBXContainerItemProxy */ = {
53 | isa = PBXContainerItemProxy;
54 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
55 | proxyType = 1;
56 | remoteGlobalIDString = 52D6D97B1BEFF229002C0205;
57 | remoteInfo = "UAParserSwift-iOS";
58 | };
59 | DD7502801C68FCFC006590AF /* PBXContainerItemProxy */ = {
60 | isa = PBXContainerItemProxy;
61 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
62 | proxyType = 1;
63 | remoteGlobalIDString = 52D6DA0E1BF000BD002C0205;
64 | remoteInfo = "UAParserSwift-macOS";
65 | };
66 | DD7502931C690C7A006590AF /* PBXContainerItemProxy */ = {
67 | isa = PBXContainerItemProxy;
68 | containerPortal = 52D6D9731BEFF229002C0205 /* Project object */;
69 | proxyType = 1;
70 | remoteGlobalIDString = 52D6D9EF1BEFFFBE002C0205;
71 | remoteInfo = "UAParserSwift-tvOS";
72 | };
73 | /* End PBXContainerItemProxy section */
74 |
75 | /* Begin PBXCopyFilesBuildPhase section */
76 | 64CD6C461FAA2183009B4F9A /* Copy Frameworks */ = {
77 | isa = PBXCopyFilesBuildPhase;
78 | buildActionMask = 2147483647;
79 | dstPath = "";
80 | dstSubfolderSpec = 10;
81 | files = (
82 | 64CD6C471FAA218E009B4F9A /* UAParserSwift.framework in Copy Frameworks */,
83 | );
84 | name = "Copy Frameworks";
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXCopyFilesBuildPhase section */
88 |
89 | /* Begin PBXFileReference section */
90 | 52D6D97C1BEFF229002C0205 /* UAParserSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UAParserSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
91 | 52D6D9861BEFF229002C0205 /* UAParserSwift-iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "UAParserSwift-iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
92 | 52D6D9E21BEFFF6E002C0205 /* UAParserSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UAParserSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
93 | 52D6D9F01BEFFFBE002C0205 /* UAParserSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UAParserSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
94 | 52D6DA0F1BF000BD002C0205 /* UAParserSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UAParserSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
95 | 643640B41FACF6CF002C4859 /* cpu-test.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "cpu-test.json"; sourceTree = ""; };
96 | 643640BC1FACFB25002C4859 /* engines-test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "engines-test.json"; sourceTree = ""; };
97 | 643640C01FACFE28002C4859 /* os-test.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "os-test.json"; sourceTree = ""; };
98 | 643640C41FADBDFC002C4859 /* device-test.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "device-test.json"; sourceTree = ""; };
99 | 643640C81FADE74A002C4859 /* browser-test.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "browser-test.json"; sourceTree = ""; };
100 | 64C2F9FE1FAF849C00E3EEDC /* UAParserSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UAParserSwift.swift; path = UAParserSwift/UAParserSwift.swift; sourceTree = ""; };
101 | 64CD6C301FAA2175009B4F9A /* TestApplication.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApplication.app; sourceTree = BUILT_PRODUCTS_DIR; };
102 | 64CD6C321FAA2175009B4F9A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
103 | 64CD6C341FAA2175009B4F9A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
104 | 64CD6C371FAA2175009B4F9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
105 | 64CD6C391FAA2175009B4F9A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
106 | 64CD6C3C1FAA2175009B4F9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
107 | 64CD6C3E1FAA2175009B4F9A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
108 | 8933C7891EB5B82A000D00A4 /* UAParserSwift_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UAParserSwift_Tests.swift; sourceTree = ""; };
109 | AD2FAA261CD0B6D800659CF4 /* UAParserSwift.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = UAParserSwift.plist; sourceTree = ""; };
110 | AD2FAA281CD0B6E100659CF4 /* UAParserSwiftTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = UAParserSwiftTests.plist; sourceTree = ""; };
111 | DD75027A1C68FCFC006590AF /* UAParserSwift-macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "UAParserSwift-macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
112 | DD75028D1C690C7A006590AF /* UAParserSwift-tvOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "UAParserSwift-tvOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
113 | /* End PBXFileReference section */
114 |
115 | /* Begin PBXFrameworksBuildPhase section */
116 | 52D6D9781BEFF229002C0205 /* Frameworks */ = {
117 | isa = PBXFrameworksBuildPhase;
118 | buildActionMask = 2147483647;
119 | files = (
120 | );
121 | runOnlyForDeploymentPostprocessing = 0;
122 | };
123 | 52D6D9831BEFF229002C0205 /* Frameworks */ = {
124 | isa = PBXFrameworksBuildPhase;
125 | buildActionMask = 2147483647;
126 | files = (
127 | 52D6D9871BEFF229002C0205 /* UAParserSwift.framework in Frameworks */,
128 | );
129 | runOnlyForDeploymentPostprocessing = 0;
130 | };
131 | 52D6D9DE1BEFFF6E002C0205 /* Frameworks */ = {
132 | isa = PBXFrameworksBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | );
136 | runOnlyForDeploymentPostprocessing = 0;
137 | };
138 | 52D6D9EC1BEFFFBE002C0205 /* Frameworks */ = {
139 | isa = PBXFrameworksBuildPhase;
140 | buildActionMask = 2147483647;
141 | files = (
142 | );
143 | runOnlyForDeploymentPostprocessing = 0;
144 | };
145 | 52D6DA0B1BF000BD002C0205 /* Frameworks */ = {
146 | isa = PBXFrameworksBuildPhase;
147 | buildActionMask = 2147483647;
148 | files = (
149 | );
150 | runOnlyForDeploymentPostprocessing = 0;
151 | };
152 | 64CD6C2D1FAA2175009B4F9A /* Frameworks */ = {
153 | isa = PBXFrameworksBuildPhase;
154 | buildActionMask = 2147483647;
155 | files = (
156 | 64CD6C451FAA2181009B4F9A /* UAParserSwift.framework in Frameworks */,
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | DD7502771C68FCFC006590AF /* Frameworks */ = {
161 | isa = PBXFrameworksBuildPhase;
162 | buildActionMask = 2147483647;
163 | files = (
164 | DD7502881C68FEDE006590AF /* UAParserSwift.framework in Frameworks */,
165 | );
166 | runOnlyForDeploymentPostprocessing = 0;
167 | };
168 | DD75028A1C690C7A006590AF /* Frameworks */ = {
169 | isa = PBXFrameworksBuildPhase;
170 | buildActionMask = 2147483647;
171 | files = (
172 | DD7502921C690C7A006590AF /* UAParserSwift.framework in Frameworks */,
173 | );
174 | runOnlyForDeploymentPostprocessing = 0;
175 | };
176 | /* End PBXFrameworksBuildPhase section */
177 |
178 | /* Begin PBXGroup section */
179 | 52D6D9721BEFF229002C0205 = {
180 | isa = PBXGroup;
181 | children = (
182 | 8933C7811EB5B7E0000D00A4 /* Sources */,
183 | 8933C7831EB5B7EB000D00A4 /* Tests */,
184 | 52D6D99C1BEFF38C002C0205 /* Configs */,
185 | 64CD6C311FAA2175009B4F9A /* TestApplication */,
186 | 52D6D97D1BEFF229002C0205 /* Products */,
187 | 64CD6C441FAA2181009B4F9A /* Frameworks */,
188 | );
189 | sourceTree = "";
190 | };
191 | 52D6D97D1BEFF229002C0205 /* Products */ = {
192 | isa = PBXGroup;
193 | children = (
194 | 52D6D97C1BEFF229002C0205 /* UAParserSwift.framework */,
195 | 52D6D9861BEFF229002C0205 /* UAParserSwift-iOS Tests.xctest */,
196 | 52D6D9E21BEFFF6E002C0205 /* UAParserSwift.framework */,
197 | 52D6D9F01BEFFFBE002C0205 /* UAParserSwift.framework */,
198 | 52D6DA0F1BF000BD002C0205 /* UAParserSwift.framework */,
199 | DD75027A1C68FCFC006590AF /* UAParserSwift-macOS Tests.xctest */,
200 | DD75028D1C690C7A006590AF /* UAParserSwift-tvOS Tests.xctest */,
201 | 64CD6C301FAA2175009B4F9A /* TestApplication.app */,
202 | );
203 | name = Products;
204 | sourceTree = "";
205 | };
206 | 52D6D99C1BEFF38C002C0205 /* Configs */ = {
207 | isa = PBXGroup;
208 | children = (
209 | DD7502721C68FC1B006590AF /* Frameworks */,
210 | DD7502731C68FC20006590AF /* Tests */,
211 | );
212 | path = Configs;
213 | sourceTree = "";
214 | };
215 | 64CD6C311FAA2175009B4F9A /* TestApplication */ = {
216 | isa = PBXGroup;
217 | children = (
218 | 64CD6C321FAA2175009B4F9A /* AppDelegate.swift */,
219 | 64CD6C341FAA2175009B4F9A /* ViewController.swift */,
220 | 64CD6C361FAA2175009B4F9A /* Main.storyboard */,
221 | 64CD6C391FAA2175009B4F9A /* Assets.xcassets */,
222 | 64CD6C3B1FAA2175009B4F9A /* LaunchScreen.storyboard */,
223 | 64CD6C3E1FAA2175009B4F9A /* Info.plist */,
224 | );
225 | path = TestApplication;
226 | sourceTree = "";
227 | };
228 | 64CD6C441FAA2181009B4F9A /* Frameworks */ = {
229 | isa = PBXGroup;
230 | children = (
231 | );
232 | name = Frameworks;
233 | sourceTree = "";
234 | };
235 | 8933C7811EB5B7E0000D00A4 /* Sources */ = {
236 | isa = PBXGroup;
237 | children = (
238 | 64C2F9FE1FAF849C00E3EEDC /* UAParserSwift.swift */,
239 | );
240 | path = Sources;
241 | sourceTree = "";
242 | };
243 | 8933C7831EB5B7EB000D00A4 /* Tests */ = {
244 | isa = PBXGroup;
245 | children = (
246 | 8933C7891EB5B82A000D00A4 /* UAParserSwift_Tests.swift */,
247 | 643640B41FACF6CF002C4859 /* cpu-test.json */,
248 | 643640BC1FACFB25002C4859 /* engines-test.json */,
249 | 643640C01FACFE28002C4859 /* os-test.json */,
250 | 643640C41FADBDFC002C4859 /* device-test.json */,
251 | 643640C81FADE74A002C4859 /* browser-test.json */,
252 | );
253 | name = Tests;
254 | path = Tests/UAParserSwiftTests;
255 | sourceTree = "";
256 | };
257 | DD7502721C68FC1B006590AF /* Frameworks */ = {
258 | isa = PBXGroup;
259 | children = (
260 | AD2FAA261CD0B6D800659CF4 /* UAParserSwift.plist */,
261 | );
262 | name = Frameworks;
263 | sourceTree = "";
264 | };
265 | DD7502731C68FC20006590AF /* Tests */ = {
266 | isa = PBXGroup;
267 | children = (
268 | AD2FAA281CD0B6E100659CF4 /* UAParserSwiftTests.plist */,
269 | );
270 | name = Tests;
271 | sourceTree = "";
272 | };
273 | /* End PBXGroup section */
274 |
275 | /* Begin PBXHeadersBuildPhase section */
276 | 52D6D9791BEFF229002C0205 /* Headers */ = {
277 | isa = PBXHeadersBuildPhase;
278 | buildActionMask = 2147483647;
279 | files = (
280 | );
281 | runOnlyForDeploymentPostprocessing = 0;
282 | };
283 | 52D6D9DF1BEFFF6E002C0205 /* Headers */ = {
284 | isa = PBXHeadersBuildPhase;
285 | buildActionMask = 2147483647;
286 | files = (
287 | );
288 | runOnlyForDeploymentPostprocessing = 0;
289 | };
290 | 52D6D9ED1BEFFFBE002C0205 /* Headers */ = {
291 | isa = PBXHeadersBuildPhase;
292 | buildActionMask = 2147483647;
293 | files = (
294 | );
295 | runOnlyForDeploymentPostprocessing = 0;
296 | };
297 | 52D6DA0C1BF000BD002C0205 /* Headers */ = {
298 | isa = PBXHeadersBuildPhase;
299 | buildActionMask = 2147483647;
300 | files = (
301 | );
302 | runOnlyForDeploymentPostprocessing = 0;
303 | };
304 | /* End PBXHeadersBuildPhase section */
305 |
306 | /* Begin PBXNativeTarget section */
307 | 52D6D97B1BEFF229002C0205 /* UAParserSwift-iOS */ = {
308 | isa = PBXNativeTarget;
309 | buildConfigurationList = 52D6D9901BEFF229002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-iOS" */;
310 | buildPhases = (
311 | 52D6D9771BEFF229002C0205 /* Sources */,
312 | 52D6D9781BEFF229002C0205 /* Frameworks */,
313 | 52D6D9791BEFF229002C0205 /* Headers */,
314 | 52D6D97A1BEFF229002C0205 /* Resources */,
315 | );
316 | buildRules = (
317 | );
318 | dependencies = (
319 | );
320 | name = "UAParserSwift-iOS";
321 | productName = UAParserSwift;
322 | productReference = 52D6D97C1BEFF229002C0205 /* UAParserSwift.framework */;
323 | productType = "com.apple.product-type.framework";
324 | };
325 | 52D6D9851BEFF229002C0205 /* UAParserSwift-iOS Tests */ = {
326 | isa = PBXNativeTarget;
327 | buildConfigurationList = 52D6D9931BEFF229002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-iOS Tests" */;
328 | buildPhases = (
329 | 52D6D9821BEFF229002C0205 /* Sources */,
330 | 52D6D9831BEFF229002C0205 /* Frameworks */,
331 | 52D6D9841BEFF229002C0205 /* Resources */,
332 | );
333 | buildRules = (
334 | );
335 | dependencies = (
336 | 52D6D9891BEFF229002C0205 /* PBXTargetDependency */,
337 | );
338 | name = "UAParserSwift-iOS Tests";
339 | productName = UAParserSwiftTests;
340 | productReference = 52D6D9861BEFF229002C0205 /* UAParserSwift-iOS Tests.xctest */;
341 | productType = "com.apple.product-type.bundle.unit-test";
342 | };
343 | 52D6D9E11BEFFF6E002C0205 /* UAParserSwift-watchOS */ = {
344 | isa = PBXNativeTarget;
345 | buildConfigurationList = 52D6D9E71BEFFF6E002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-watchOS" */;
346 | buildPhases = (
347 | 52D6D9DD1BEFFF6E002C0205 /* Sources */,
348 | 52D6D9DE1BEFFF6E002C0205 /* Frameworks */,
349 | 52D6D9DF1BEFFF6E002C0205 /* Headers */,
350 | 52D6D9E01BEFFF6E002C0205 /* Resources */,
351 | );
352 | buildRules = (
353 | );
354 | dependencies = (
355 | );
356 | name = "UAParserSwift-watchOS";
357 | productName = "UAParserSwift-watchOS";
358 | productReference = 52D6D9E21BEFFF6E002C0205 /* UAParserSwift.framework */;
359 | productType = "com.apple.product-type.framework";
360 | };
361 | 52D6D9EF1BEFFFBE002C0205 /* UAParserSwift-tvOS */ = {
362 | isa = PBXNativeTarget;
363 | buildConfigurationList = 52D6DA011BEFFFBE002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-tvOS" */;
364 | buildPhases = (
365 | 52D6D9EB1BEFFFBE002C0205 /* Sources */,
366 | 52D6D9EC1BEFFFBE002C0205 /* Frameworks */,
367 | 52D6D9ED1BEFFFBE002C0205 /* Headers */,
368 | 52D6D9EE1BEFFFBE002C0205 /* Resources */,
369 | );
370 | buildRules = (
371 | );
372 | dependencies = (
373 | );
374 | name = "UAParserSwift-tvOS";
375 | productName = "UAParserSwift-tvOS";
376 | productReference = 52D6D9F01BEFFFBE002C0205 /* UAParserSwift.framework */;
377 | productType = "com.apple.product-type.framework";
378 | };
379 | 52D6DA0E1BF000BD002C0205 /* UAParserSwift-macOS */ = {
380 | isa = PBXNativeTarget;
381 | buildConfigurationList = 52D6DA201BF000BD002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-macOS" */;
382 | buildPhases = (
383 | 52D6DA0A1BF000BD002C0205 /* Sources */,
384 | 52D6DA0B1BF000BD002C0205 /* Frameworks */,
385 | 52D6DA0C1BF000BD002C0205 /* Headers */,
386 | 52D6DA0D1BF000BD002C0205 /* Resources */,
387 | );
388 | buildRules = (
389 | );
390 | dependencies = (
391 | );
392 | name = "UAParserSwift-macOS";
393 | productName = "UAParserSwift-macOS";
394 | productReference = 52D6DA0F1BF000BD002C0205 /* UAParserSwift.framework */;
395 | productType = "com.apple.product-type.framework";
396 | };
397 | 64CD6C2F1FAA2175009B4F9A /* TestApplication */ = {
398 | isa = PBXNativeTarget;
399 | buildConfigurationList = 64CD6C411FAA2175009B4F9A /* Build configuration list for PBXNativeTarget "TestApplication" */;
400 | buildPhases = (
401 | 64CD6C2C1FAA2175009B4F9A /* Sources */,
402 | 64CD6C2D1FAA2175009B4F9A /* Frameworks */,
403 | 64CD6C2E1FAA2175009B4F9A /* Resources */,
404 | 64CD6C461FAA2183009B4F9A /* Copy Frameworks */,
405 | );
406 | buildRules = (
407 | );
408 | dependencies = (
409 | 64CD6C431FAA217B009B4F9A /* PBXTargetDependency */,
410 | );
411 | name = TestApplication;
412 | productName = TestApplication;
413 | productReference = 64CD6C301FAA2175009B4F9A /* TestApplication.app */;
414 | productType = "com.apple.product-type.application";
415 | };
416 | DD7502791C68FCFC006590AF /* UAParserSwift-macOS Tests */ = {
417 | isa = PBXNativeTarget;
418 | buildConfigurationList = DD7502821C68FCFC006590AF /* Build configuration list for PBXNativeTarget "UAParserSwift-macOS Tests" */;
419 | buildPhases = (
420 | DD7502761C68FCFC006590AF /* Sources */,
421 | DD7502771C68FCFC006590AF /* Frameworks */,
422 | DD7502781C68FCFC006590AF /* Resources */,
423 | );
424 | buildRules = (
425 | );
426 | dependencies = (
427 | DD7502811C68FCFC006590AF /* PBXTargetDependency */,
428 | );
429 | name = "UAParserSwift-macOS Tests";
430 | productName = "UAParserSwift-OS Tests";
431 | productReference = DD75027A1C68FCFC006590AF /* UAParserSwift-macOS Tests.xctest */;
432 | productType = "com.apple.product-type.bundle.unit-test";
433 | };
434 | DD75028C1C690C7A006590AF /* UAParserSwift-tvOS Tests */ = {
435 | isa = PBXNativeTarget;
436 | buildConfigurationList = DD7502951C690C7A006590AF /* Build configuration list for PBXNativeTarget "UAParserSwift-tvOS Tests" */;
437 | buildPhases = (
438 | DD7502891C690C7A006590AF /* Sources */,
439 | DD75028A1C690C7A006590AF /* Frameworks */,
440 | DD75028B1C690C7A006590AF /* Resources */,
441 | );
442 | buildRules = (
443 | );
444 | dependencies = (
445 | DD7502941C690C7A006590AF /* PBXTargetDependency */,
446 | );
447 | name = "UAParserSwift-tvOS Tests";
448 | productName = "UAParserSwift-tvOS Tests";
449 | productReference = DD75028D1C690C7A006590AF /* UAParserSwift-tvOS Tests.xctest */;
450 | productType = "com.apple.product-type.bundle.unit-test";
451 | };
452 | /* End PBXNativeTarget section */
453 |
454 | /* Begin PBXProject section */
455 | 52D6D9731BEFF229002C0205 /* Project object */ = {
456 | isa = PBXProject;
457 | attributes = {
458 | LastSwiftUpdateCheck = 0910;
459 | LastUpgradeCheck = 1220;
460 | ORGANIZATIONNAME = UAParserSwift;
461 | TargetAttributes = {
462 | 52D6D97B1BEFF229002C0205 = {
463 | CreatedOnToolsVersion = 7.1;
464 | LastSwiftMigration = 1220;
465 | };
466 | 52D6D9851BEFF229002C0205 = {
467 | CreatedOnToolsVersion = 7.1;
468 | LastSwiftMigration = 0800;
469 | };
470 | 52D6D9E11BEFFF6E002C0205 = {
471 | CreatedOnToolsVersion = 7.1;
472 | LastSwiftMigration = 0910;
473 | };
474 | 52D6D9EF1BEFFFBE002C0205 = {
475 | CreatedOnToolsVersion = 7.1;
476 | LastSwiftMigration = 0910;
477 | };
478 | 52D6DA0E1BF000BD002C0205 = {
479 | CreatedOnToolsVersion = 7.1;
480 | LastSwiftMigration = 0910;
481 | };
482 | 64CD6C2F1FAA2175009B4F9A = {
483 | CreatedOnToolsVersion = 9.1;
484 | LastSwiftMigration = 1220;
485 | ProvisioningStyle = Automatic;
486 | };
487 | DD7502791C68FCFC006590AF = {
488 | CreatedOnToolsVersion = 7.2.1;
489 | LastSwiftMigration = 0800;
490 | };
491 | DD75028C1C690C7A006590AF = {
492 | CreatedOnToolsVersion = 7.2.1;
493 | LastSwiftMigration = 0800;
494 | };
495 | };
496 | };
497 | buildConfigurationList = 52D6D9761BEFF229002C0205 /* Build configuration list for PBXProject "UAParserSwift" */;
498 | compatibilityVersion = "Xcode 6.3";
499 | developmentRegion = en;
500 | hasScannedForEncodings = 0;
501 | knownRegions = (
502 | en,
503 | Base,
504 | );
505 | mainGroup = 52D6D9721BEFF229002C0205;
506 | productRefGroup = 52D6D97D1BEFF229002C0205 /* Products */;
507 | projectDirPath = "";
508 | projectRoot = "";
509 | targets = (
510 | 52D6D97B1BEFF229002C0205 /* UAParserSwift-iOS */,
511 | 52D6DA0E1BF000BD002C0205 /* UAParserSwift-macOS */,
512 | 52D6D9E11BEFFF6E002C0205 /* UAParserSwift-watchOS */,
513 | 52D6D9EF1BEFFFBE002C0205 /* UAParserSwift-tvOS */,
514 | 52D6D9851BEFF229002C0205 /* UAParserSwift-iOS Tests */,
515 | DD7502791C68FCFC006590AF /* UAParserSwift-macOS Tests */,
516 | DD75028C1C690C7A006590AF /* UAParserSwift-tvOS Tests */,
517 | 64CD6C2F1FAA2175009B4F9A /* TestApplication */,
518 | );
519 | };
520 | /* End PBXProject section */
521 |
522 | /* Begin PBXResourcesBuildPhase section */
523 | 52D6D97A1BEFF229002C0205 /* Resources */ = {
524 | isa = PBXResourcesBuildPhase;
525 | buildActionMask = 2147483647;
526 | files = (
527 | );
528 | runOnlyForDeploymentPostprocessing = 0;
529 | };
530 | 52D6D9841BEFF229002C0205 /* Resources */ = {
531 | isa = PBXResourcesBuildPhase;
532 | buildActionMask = 2147483647;
533 | files = (
534 | 643640C51FADBDFC002C4859 /* device-test.json in Resources */,
535 | 643640B51FACF6CF002C4859 /* cpu-test.json in Resources */,
536 | 643640BD1FACFB25002C4859 /* engines-test.json in Resources */,
537 | 643640C11FACFE28002C4859 /* os-test.json in Resources */,
538 | 643640C91FADE74A002C4859 /* browser-test.json in Resources */,
539 | );
540 | runOnlyForDeploymentPostprocessing = 0;
541 | };
542 | 52D6D9E01BEFFF6E002C0205 /* Resources */ = {
543 | isa = PBXResourcesBuildPhase;
544 | buildActionMask = 2147483647;
545 | files = (
546 | );
547 | runOnlyForDeploymentPostprocessing = 0;
548 | };
549 | 52D6D9EE1BEFFFBE002C0205 /* Resources */ = {
550 | isa = PBXResourcesBuildPhase;
551 | buildActionMask = 2147483647;
552 | files = (
553 | );
554 | runOnlyForDeploymentPostprocessing = 0;
555 | };
556 | 52D6DA0D1BF000BD002C0205 /* Resources */ = {
557 | isa = PBXResourcesBuildPhase;
558 | buildActionMask = 2147483647;
559 | files = (
560 | );
561 | runOnlyForDeploymentPostprocessing = 0;
562 | };
563 | 64CD6C2E1FAA2175009B4F9A /* Resources */ = {
564 | isa = PBXResourcesBuildPhase;
565 | buildActionMask = 2147483647;
566 | files = (
567 | 64CD6C3D1FAA2175009B4F9A /* LaunchScreen.storyboard in Resources */,
568 | 64CD6C3A1FAA2175009B4F9A /* Assets.xcassets in Resources */,
569 | 64CD6C381FAA2175009B4F9A /* Main.storyboard in Resources */,
570 | );
571 | runOnlyForDeploymentPostprocessing = 0;
572 | };
573 | DD7502781C68FCFC006590AF /* Resources */ = {
574 | isa = PBXResourcesBuildPhase;
575 | buildActionMask = 2147483647;
576 | files = (
577 | 643640C61FADBDFC002C4859 /* device-test.json in Resources */,
578 | 643640B61FACF6CF002C4859 /* cpu-test.json in Resources */,
579 | 643640BE1FACFB25002C4859 /* engines-test.json in Resources */,
580 | 643640C21FACFE28002C4859 /* os-test.json in Resources */,
581 | 643640CA1FADE74A002C4859 /* browser-test.json in Resources */,
582 | );
583 | runOnlyForDeploymentPostprocessing = 0;
584 | };
585 | DD75028B1C690C7A006590AF /* Resources */ = {
586 | isa = PBXResourcesBuildPhase;
587 | buildActionMask = 2147483647;
588 | files = (
589 | 643640C71FADBDFC002C4859 /* device-test.json in Resources */,
590 | 643640B71FACF6CF002C4859 /* cpu-test.json in Resources */,
591 | 643640BF1FACFB25002C4859 /* engines-test.json in Resources */,
592 | 643640C31FACFE28002C4859 /* os-test.json in Resources */,
593 | 643640CB1FADE74A002C4859 /* browser-test.json in Resources */,
594 | );
595 | runOnlyForDeploymentPostprocessing = 0;
596 | };
597 | /* End PBXResourcesBuildPhase section */
598 |
599 | /* Begin PBXSourcesBuildPhase section */
600 | 52D6D9771BEFF229002C0205 /* Sources */ = {
601 | isa = PBXSourcesBuildPhase;
602 | buildActionMask = 2147483647;
603 | files = (
604 | 64C2F9FF1FAF849C00E3EEDC /* UAParserSwift.swift in Sources */,
605 | );
606 | runOnlyForDeploymentPostprocessing = 0;
607 | };
608 | 52D6D9821BEFF229002C0205 /* Sources */ = {
609 | isa = PBXSourcesBuildPhase;
610 | buildActionMask = 2147483647;
611 | files = (
612 | 8933C7901EB5B82D000D00A4 /* UAParserSwift_Tests.swift in Sources */,
613 | );
614 | runOnlyForDeploymentPostprocessing = 0;
615 | };
616 | 52D6D9DD1BEFFF6E002C0205 /* Sources */ = {
617 | isa = PBXSourcesBuildPhase;
618 | buildActionMask = 2147483647;
619 | files = (
620 | 64C2FA011FAF849C00E3EEDC /* UAParserSwift.swift in Sources */,
621 | );
622 | runOnlyForDeploymentPostprocessing = 0;
623 | };
624 | 52D6D9EB1BEFFFBE002C0205 /* Sources */ = {
625 | isa = PBXSourcesBuildPhase;
626 | buildActionMask = 2147483647;
627 | files = (
628 | 64C2FA021FAF849C00E3EEDC /* UAParserSwift.swift in Sources */,
629 | );
630 | runOnlyForDeploymentPostprocessing = 0;
631 | };
632 | 52D6DA0A1BF000BD002C0205 /* Sources */ = {
633 | isa = PBXSourcesBuildPhase;
634 | buildActionMask = 2147483647;
635 | files = (
636 | 64C2FA001FAF849C00E3EEDC /* UAParserSwift.swift in Sources */,
637 | );
638 | runOnlyForDeploymentPostprocessing = 0;
639 | };
640 | 64CD6C2C1FAA2175009B4F9A /* Sources */ = {
641 | isa = PBXSourcesBuildPhase;
642 | buildActionMask = 2147483647;
643 | files = (
644 | 64CD6C351FAA2175009B4F9A /* ViewController.swift in Sources */,
645 | 64CD6C331FAA2175009B4F9A /* AppDelegate.swift in Sources */,
646 | );
647 | runOnlyForDeploymentPostprocessing = 0;
648 | };
649 | DD7502761C68FCFC006590AF /* Sources */ = {
650 | isa = PBXSourcesBuildPhase;
651 | buildActionMask = 2147483647;
652 | files = (
653 | 8933C78F1EB5B82C000D00A4 /* UAParserSwift_Tests.swift in Sources */,
654 | );
655 | runOnlyForDeploymentPostprocessing = 0;
656 | };
657 | DD7502891C690C7A006590AF /* Sources */ = {
658 | isa = PBXSourcesBuildPhase;
659 | buildActionMask = 2147483647;
660 | files = (
661 | 8933C78E1EB5B82C000D00A4 /* UAParserSwift_Tests.swift in Sources */,
662 | );
663 | runOnlyForDeploymentPostprocessing = 0;
664 | };
665 | /* End PBXSourcesBuildPhase section */
666 |
667 | /* Begin PBXTargetDependency section */
668 | 52D6D9891BEFF229002C0205 /* PBXTargetDependency */ = {
669 | isa = PBXTargetDependency;
670 | target = 52D6D97B1BEFF229002C0205 /* UAParserSwift-iOS */;
671 | targetProxy = 52D6D9881BEFF229002C0205 /* PBXContainerItemProxy */;
672 | };
673 | 64CD6C431FAA217B009B4F9A /* PBXTargetDependency */ = {
674 | isa = PBXTargetDependency;
675 | target = 52D6D97B1BEFF229002C0205 /* UAParserSwift-iOS */;
676 | targetProxy = 64CD6C421FAA217B009B4F9A /* PBXContainerItemProxy */;
677 | };
678 | DD7502811C68FCFC006590AF /* PBXTargetDependency */ = {
679 | isa = PBXTargetDependency;
680 | target = 52D6DA0E1BF000BD002C0205 /* UAParserSwift-macOS */;
681 | targetProxy = DD7502801C68FCFC006590AF /* PBXContainerItemProxy */;
682 | };
683 | DD7502941C690C7A006590AF /* PBXTargetDependency */ = {
684 | isa = PBXTargetDependency;
685 | target = 52D6D9EF1BEFFFBE002C0205 /* UAParserSwift-tvOS */;
686 | targetProxy = DD7502931C690C7A006590AF /* PBXContainerItemProxy */;
687 | };
688 | /* End PBXTargetDependency section */
689 |
690 | /* Begin PBXVariantGroup section */
691 | 64CD6C361FAA2175009B4F9A /* Main.storyboard */ = {
692 | isa = PBXVariantGroup;
693 | children = (
694 | 64CD6C371FAA2175009B4F9A /* Base */,
695 | );
696 | name = Main.storyboard;
697 | sourceTree = "";
698 | };
699 | 64CD6C3B1FAA2175009B4F9A /* LaunchScreen.storyboard */ = {
700 | isa = PBXVariantGroup;
701 | children = (
702 | 64CD6C3C1FAA2175009B4F9A /* Base */,
703 | );
704 | name = LaunchScreen.storyboard;
705 | sourceTree = "";
706 | };
707 | /* End PBXVariantGroup section */
708 |
709 | /* Begin XCBuildConfiguration section */
710 | 52D6D98E1BEFF229002C0205 /* Debug */ = {
711 | isa = XCBuildConfiguration;
712 | buildSettings = {
713 | ALWAYS_SEARCH_USER_PATHS = NO;
714 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
715 | CLANG_CXX_LIBRARY = "libc++";
716 | CLANG_ENABLE_MODULES = YES;
717 | CLANG_ENABLE_OBJC_ARC = YES;
718 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
719 | CLANG_WARN_BOOL_CONVERSION = YES;
720 | CLANG_WARN_COMMA = YES;
721 | CLANG_WARN_CONSTANT_CONVERSION = YES;
722 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
723 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
724 | CLANG_WARN_EMPTY_BODY = YES;
725 | CLANG_WARN_ENUM_CONVERSION = YES;
726 | CLANG_WARN_INFINITE_RECURSION = YES;
727 | CLANG_WARN_INT_CONVERSION = YES;
728 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
729 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
730 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
731 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
732 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
733 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
734 | CLANG_WARN_STRICT_PROTOTYPES = YES;
735 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
736 | CLANG_WARN_UNREACHABLE_CODE = YES;
737 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
738 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
739 | COPY_PHASE_STRIP = NO;
740 | CURRENT_PROJECT_VERSION = 1;
741 | DEBUG_INFORMATION_FORMAT = dwarf;
742 | ENABLE_STRICT_OBJC_MSGSEND = YES;
743 | ENABLE_TESTABILITY = YES;
744 | GCC_C_LANGUAGE_STANDARD = gnu99;
745 | GCC_DYNAMIC_NO_PIC = NO;
746 | GCC_NO_COMMON_BLOCKS = YES;
747 | GCC_OPTIMIZATION_LEVEL = 0;
748 | GCC_PREPROCESSOR_DEFINITIONS = (
749 | "DEBUG=1",
750 | "$(inherited)",
751 | );
752 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
753 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
754 | GCC_WARN_UNDECLARED_SELECTOR = YES;
755 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
756 | GCC_WARN_UNUSED_FUNCTION = YES;
757 | GCC_WARN_UNUSED_VARIABLE = YES;
758 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
759 | MTL_ENABLE_DEBUG_INFO = YES;
760 | ONLY_ACTIVE_ARCH = YES;
761 | SDKROOT = iphoneos;
762 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
763 | SWIFT_VERSION = 4.0;
764 | TARGETED_DEVICE_FAMILY = "1,2";
765 | VERSIONING_SYSTEM = "apple-generic";
766 | VERSION_INFO_PREFIX = "";
767 | };
768 | name = Debug;
769 | };
770 | 52D6D98F1BEFF229002C0205 /* Release */ = {
771 | isa = XCBuildConfiguration;
772 | buildSettings = {
773 | ALWAYS_SEARCH_USER_PATHS = NO;
774 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
775 | CLANG_CXX_LIBRARY = "libc++";
776 | CLANG_ENABLE_MODULES = YES;
777 | CLANG_ENABLE_OBJC_ARC = YES;
778 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
779 | CLANG_WARN_BOOL_CONVERSION = YES;
780 | CLANG_WARN_COMMA = YES;
781 | CLANG_WARN_CONSTANT_CONVERSION = YES;
782 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
783 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
784 | CLANG_WARN_EMPTY_BODY = YES;
785 | CLANG_WARN_ENUM_CONVERSION = YES;
786 | CLANG_WARN_INFINITE_RECURSION = YES;
787 | CLANG_WARN_INT_CONVERSION = YES;
788 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
789 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
790 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
791 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
792 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
793 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
794 | CLANG_WARN_STRICT_PROTOTYPES = YES;
795 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
796 | CLANG_WARN_UNREACHABLE_CODE = YES;
797 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
798 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
799 | COPY_PHASE_STRIP = NO;
800 | CURRENT_PROJECT_VERSION = 1;
801 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
802 | ENABLE_NS_ASSERTIONS = NO;
803 | ENABLE_STRICT_OBJC_MSGSEND = YES;
804 | GCC_C_LANGUAGE_STANDARD = gnu99;
805 | GCC_NO_COMMON_BLOCKS = YES;
806 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
807 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
808 | GCC_WARN_UNDECLARED_SELECTOR = YES;
809 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
810 | GCC_WARN_UNUSED_FUNCTION = YES;
811 | GCC_WARN_UNUSED_VARIABLE = YES;
812 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
813 | MTL_ENABLE_DEBUG_INFO = NO;
814 | SDKROOT = iphoneos;
815 | SWIFT_VERSION = 4.0;
816 | TARGETED_DEVICE_FAMILY = "1,2";
817 | VALIDATE_PRODUCT = YES;
818 | VERSIONING_SYSTEM = "apple-generic";
819 | VERSION_INFO_PREFIX = "";
820 | };
821 | name = Release;
822 | };
823 | 52D6D9911BEFF229002C0205 /* Debug */ = {
824 | isa = XCBuildConfiguration;
825 | buildSettings = {
826 | APPLICATION_EXTENSION_API_ONLY = YES;
827 | CLANG_ENABLE_MODULES = YES;
828 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
829 | DEFINES_MODULE = YES;
830 | DYLIB_COMPATIBILITY_VERSION = 1;
831 | DYLIB_CURRENT_VERSION = 1;
832 | DYLIB_INSTALL_NAME_BASE = "@rpath";
833 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
834 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
835 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
836 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
837 | ONLY_ACTIVE_ARCH = NO;
838 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-iOS";
839 | PRODUCT_NAME = UAParserSwift;
840 | SKIP_INSTALL = YES;
841 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
842 | SWIFT_VERSION = 5.0;
843 | };
844 | name = Debug;
845 | };
846 | 52D6D9921BEFF229002C0205 /* Release */ = {
847 | isa = XCBuildConfiguration;
848 | buildSettings = {
849 | APPLICATION_EXTENSION_API_ONLY = YES;
850 | CLANG_ENABLE_MODULES = YES;
851 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
852 | DEFINES_MODULE = YES;
853 | DYLIB_COMPATIBILITY_VERSION = 1;
854 | DYLIB_CURRENT_VERSION = 1;
855 | DYLIB_INSTALL_NAME_BASE = "@rpath";
856 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
857 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
858 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
859 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
860 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-iOS";
861 | PRODUCT_NAME = UAParserSwift;
862 | SKIP_INSTALL = YES;
863 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
864 | SWIFT_VERSION = 5.0;
865 | };
866 | name = Release;
867 | };
868 | 52D6D9941BEFF229002C0205 /* Debug */ = {
869 | isa = XCBuildConfiguration;
870 | buildSettings = {
871 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
872 | CLANG_ENABLE_MODULES = YES;
873 | INFOPLIST_FILE = Configs/UAParserSwiftTests.plist;
874 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
875 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-iOS-Tests";
876 | PRODUCT_NAME = "$(TARGET_NAME)";
877 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
878 | SWIFT_VERSION = 4.0;
879 | };
880 | name = Debug;
881 | };
882 | 52D6D9951BEFF229002C0205 /* Release */ = {
883 | isa = XCBuildConfiguration;
884 | buildSettings = {
885 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
886 | CLANG_ENABLE_MODULES = YES;
887 | INFOPLIST_FILE = Configs/UAParserSwiftTests.plist;
888 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
889 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-iOS-Tests";
890 | PRODUCT_NAME = "$(TARGET_NAME)";
891 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
892 | SWIFT_VERSION = 4.0;
893 | };
894 | name = Release;
895 | };
896 | 52D6D9E81BEFFF6E002C0205 /* Debug */ = {
897 | isa = XCBuildConfiguration;
898 | buildSettings = {
899 | APPLICATION_EXTENSION_API_ONLY = YES;
900 | CLANG_ENABLE_MODULES = YES;
901 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
902 | DEFINES_MODULE = YES;
903 | DYLIB_COMPATIBILITY_VERSION = 1;
904 | DYLIB_CURRENT_VERSION = 1;
905 | DYLIB_INSTALL_NAME_BASE = "@rpath";
906 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
907 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
908 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
909 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-watchOS";
910 | PRODUCT_NAME = UAParserSwift;
911 | SDKROOT = watchos;
912 | SKIP_INSTALL = YES;
913 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
914 | SWIFT_VERSION = 4.0;
915 | TARGETED_DEVICE_FAMILY = 4;
916 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
917 | };
918 | name = Debug;
919 | };
920 | 52D6D9E91BEFFF6E002C0205 /* Release */ = {
921 | isa = XCBuildConfiguration;
922 | buildSettings = {
923 | APPLICATION_EXTENSION_API_ONLY = YES;
924 | CLANG_ENABLE_MODULES = YES;
925 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
926 | DEFINES_MODULE = YES;
927 | DYLIB_COMPATIBILITY_VERSION = 1;
928 | DYLIB_CURRENT_VERSION = 1;
929 | DYLIB_INSTALL_NAME_BASE = "@rpath";
930 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
931 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
932 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
933 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-watchOS";
934 | PRODUCT_NAME = UAParserSwift;
935 | SDKROOT = watchos;
936 | SKIP_INSTALL = YES;
937 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
938 | SWIFT_VERSION = 4.0;
939 | TARGETED_DEVICE_FAMILY = 4;
940 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
941 | };
942 | name = Release;
943 | };
944 | 52D6DA021BEFFFBE002C0205 /* Debug */ = {
945 | isa = XCBuildConfiguration;
946 | buildSettings = {
947 | APPLICATION_EXTENSION_API_ONLY = YES;
948 | CLANG_ENABLE_MODULES = YES;
949 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
950 | DEFINES_MODULE = YES;
951 | DYLIB_COMPATIBILITY_VERSION = 1;
952 | DYLIB_CURRENT_VERSION = 1;
953 | DYLIB_INSTALL_NAME_BASE = "@rpath";
954 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
955 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
956 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
957 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-tvOS";
958 | PRODUCT_NAME = UAParserSwift;
959 | SDKROOT = appletvos;
960 | SKIP_INSTALL = YES;
961 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
962 | SWIFT_VERSION = 4.0;
963 | TARGETED_DEVICE_FAMILY = 3;
964 | TVOS_DEPLOYMENT_TARGET = 12.0;
965 | };
966 | name = Debug;
967 | };
968 | 52D6DA031BEFFFBE002C0205 /* Release */ = {
969 | isa = XCBuildConfiguration;
970 | buildSettings = {
971 | APPLICATION_EXTENSION_API_ONLY = YES;
972 | CLANG_ENABLE_MODULES = YES;
973 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
974 | DEFINES_MODULE = YES;
975 | DYLIB_COMPATIBILITY_VERSION = 1;
976 | DYLIB_CURRENT_VERSION = 1;
977 | DYLIB_INSTALL_NAME_BASE = "@rpath";
978 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
979 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
980 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
981 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-tvOS";
982 | PRODUCT_NAME = UAParserSwift;
983 | SDKROOT = appletvos;
984 | SKIP_INSTALL = YES;
985 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
986 | SWIFT_VERSION = 4.0;
987 | TARGETED_DEVICE_FAMILY = 3;
988 | TVOS_DEPLOYMENT_TARGET = 12.0;
989 | };
990 | name = Release;
991 | };
992 | 52D6DA211BF000BD002C0205 /* Debug */ = {
993 | isa = XCBuildConfiguration;
994 | buildSettings = {
995 | APPLICATION_EXTENSION_API_ONLY = YES;
996 | CLANG_ENABLE_MODULES = YES;
997 | CODE_SIGN_IDENTITY = "-";
998 | COMBINE_HIDPI_IMAGES = YES;
999 | DEFINES_MODULE = YES;
1000 | DYLIB_COMPATIBILITY_VERSION = 1;
1001 | DYLIB_CURRENT_VERSION = 1;
1002 | DYLIB_INSTALL_NAME_BASE = "@rpath";
1003 | FRAMEWORK_VERSION = A;
1004 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
1005 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
1006 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
1007 | MACOSX_DEPLOYMENT_TARGET = 10.10;
1008 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-macOS";
1009 | PRODUCT_NAME = UAParserSwift;
1010 | SDKROOT = macosx;
1011 | SKIP_INSTALL = YES;
1012 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
1013 | SWIFT_VERSION = 4.0;
1014 | };
1015 | name = Debug;
1016 | };
1017 | 52D6DA221BF000BD002C0205 /* Release */ = {
1018 | isa = XCBuildConfiguration;
1019 | buildSettings = {
1020 | APPLICATION_EXTENSION_API_ONLY = YES;
1021 | CLANG_ENABLE_MODULES = YES;
1022 | CODE_SIGN_IDENTITY = "-";
1023 | COMBINE_HIDPI_IMAGES = YES;
1024 | DEFINES_MODULE = YES;
1025 | DYLIB_COMPATIBILITY_VERSION = 1;
1026 | DYLIB_CURRENT_VERSION = 1;
1027 | DYLIB_INSTALL_NAME_BASE = "@rpath";
1028 | FRAMEWORK_VERSION = A;
1029 | INFOPLIST_FILE = Configs/UAParserSwift.plist;
1030 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
1031 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
1032 | MACOSX_DEPLOYMENT_TARGET = 10.10;
1033 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-macOS";
1034 | PRODUCT_NAME = UAParserSwift;
1035 | SDKROOT = macosx;
1036 | SKIP_INSTALL = YES;
1037 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1038 | SWIFT_VERSION = 4.0;
1039 | };
1040 | name = Release;
1041 | };
1042 | 64CD6C3F1FAA2175009B4F9A /* Debug */ = {
1043 | isa = XCBuildConfiguration;
1044 | buildSettings = {
1045 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1046 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1047 | CLANG_ANALYZER_NONNULL = YES;
1048 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1049 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
1050 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1051 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1052 | CODE_SIGN_IDENTITY = "iPhone Developer";
1053 | CODE_SIGN_STYLE = Automatic;
1054 | GCC_C_LANGUAGE_STANDARD = gnu11;
1055 | INFOPLIST_FILE = TestApplication/Info.plist;
1056 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
1057 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1058 | LIBRARY_SEARCH_PATHS = "";
1059 | PRODUCT_BUNDLE_IDENTIFIER = com.danielemargutti.TestApplication;
1060 | PRODUCT_NAME = "$(TARGET_NAME)";
1061 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
1062 | SWIFT_VERSION = 5.0;
1063 | TARGETED_DEVICE_FAMILY = "1,2";
1064 | };
1065 | name = Debug;
1066 | };
1067 | 64CD6C401FAA2175009B4F9A /* Release */ = {
1068 | isa = XCBuildConfiguration;
1069 | buildSettings = {
1070 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1071 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1072 | CLANG_ANALYZER_NONNULL = YES;
1073 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
1074 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
1075 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1076 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
1077 | CODE_SIGN_IDENTITY = "iPhone Developer";
1078 | CODE_SIGN_STYLE = Automatic;
1079 | GCC_C_LANGUAGE_STANDARD = gnu11;
1080 | INFOPLIST_FILE = TestApplication/Info.plist;
1081 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
1082 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1083 | LIBRARY_SEARCH_PATHS = "";
1084 | PRODUCT_BUNDLE_IDENTIFIER = com.danielemargutti.TestApplication;
1085 | PRODUCT_NAME = "$(TARGET_NAME)";
1086 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1087 | SWIFT_VERSION = 5.0;
1088 | TARGETED_DEVICE_FAMILY = "1,2";
1089 | };
1090 | name = Release;
1091 | };
1092 | DD7502831C68FCFC006590AF /* Debug */ = {
1093 | isa = XCBuildConfiguration;
1094 | buildSettings = {
1095 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1096 | CODE_SIGN_IDENTITY = "-";
1097 | COMBINE_HIDPI_IMAGES = YES;
1098 | INFOPLIST_FILE = Configs/UAParserSwiftTests.plist;
1099 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
1100 | MACOSX_DEPLOYMENT_TARGET = 10.11;
1101 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-macOS-Tests";
1102 | PRODUCT_NAME = "$(TARGET_NAME)";
1103 | SDKROOT = macosx;
1104 | SWIFT_VERSION = 4.0;
1105 | };
1106 | name = Debug;
1107 | };
1108 | DD7502841C68FCFC006590AF /* Release */ = {
1109 | isa = XCBuildConfiguration;
1110 | buildSettings = {
1111 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1112 | CODE_SIGN_IDENTITY = "-";
1113 | COMBINE_HIDPI_IMAGES = YES;
1114 | INFOPLIST_FILE = Configs/UAParserSwiftTests.plist;
1115 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
1116 | MACOSX_DEPLOYMENT_TARGET = 10.11;
1117 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-macOS-Tests";
1118 | PRODUCT_NAME = "$(TARGET_NAME)";
1119 | SDKROOT = macosx;
1120 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1121 | SWIFT_VERSION = 4.0;
1122 | };
1123 | name = Release;
1124 | };
1125 | DD7502961C690C7A006590AF /* Debug */ = {
1126 | isa = XCBuildConfiguration;
1127 | buildSettings = {
1128 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1129 | INFOPLIST_FILE = Configs/UAParserSwiftTests.plist;
1130 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1131 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-tvOS-Tests";
1132 | PRODUCT_NAME = "$(TARGET_NAME)";
1133 | SDKROOT = appletvos;
1134 | SWIFT_VERSION = 4.0;
1135 | TVOS_DEPLOYMENT_TARGET = 12.0;
1136 | };
1137 | name = Debug;
1138 | };
1139 | DD7502971C690C7A006590AF /* Release */ = {
1140 | isa = XCBuildConfiguration;
1141 | buildSettings = {
1142 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1143 | INFOPLIST_FILE = Configs/UAParserSwiftTests.plist;
1144 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1145 | PRODUCT_BUNDLE_IDENTIFIER = "com.UAParserSwift.UAParserSwift-tvOS-Tests";
1146 | PRODUCT_NAME = "$(TARGET_NAME)";
1147 | SDKROOT = appletvos;
1148 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1149 | SWIFT_VERSION = 4.0;
1150 | TVOS_DEPLOYMENT_TARGET = 12.0;
1151 | };
1152 | name = Release;
1153 | };
1154 | /* End XCBuildConfiguration section */
1155 |
1156 | /* Begin XCConfigurationList section */
1157 | 52D6D9761BEFF229002C0205 /* Build configuration list for PBXProject "UAParserSwift" */ = {
1158 | isa = XCConfigurationList;
1159 | buildConfigurations = (
1160 | 52D6D98E1BEFF229002C0205 /* Debug */,
1161 | 52D6D98F1BEFF229002C0205 /* Release */,
1162 | );
1163 | defaultConfigurationIsVisible = 0;
1164 | defaultConfigurationName = Release;
1165 | };
1166 | 52D6D9901BEFF229002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-iOS" */ = {
1167 | isa = XCConfigurationList;
1168 | buildConfigurations = (
1169 | 52D6D9911BEFF229002C0205 /* Debug */,
1170 | 52D6D9921BEFF229002C0205 /* Release */,
1171 | );
1172 | defaultConfigurationIsVisible = 0;
1173 | defaultConfigurationName = Release;
1174 | };
1175 | 52D6D9931BEFF229002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-iOS Tests" */ = {
1176 | isa = XCConfigurationList;
1177 | buildConfigurations = (
1178 | 52D6D9941BEFF229002C0205 /* Debug */,
1179 | 52D6D9951BEFF229002C0205 /* Release */,
1180 | );
1181 | defaultConfigurationIsVisible = 0;
1182 | defaultConfigurationName = Release;
1183 | };
1184 | 52D6D9E71BEFFF6E002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-watchOS" */ = {
1185 | isa = XCConfigurationList;
1186 | buildConfigurations = (
1187 | 52D6D9E81BEFFF6E002C0205 /* Debug */,
1188 | 52D6D9E91BEFFF6E002C0205 /* Release */,
1189 | );
1190 | defaultConfigurationIsVisible = 0;
1191 | defaultConfigurationName = Release;
1192 | };
1193 | 52D6DA011BEFFFBE002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-tvOS" */ = {
1194 | isa = XCConfigurationList;
1195 | buildConfigurations = (
1196 | 52D6DA021BEFFFBE002C0205 /* Debug */,
1197 | 52D6DA031BEFFFBE002C0205 /* Release */,
1198 | );
1199 | defaultConfigurationIsVisible = 0;
1200 | defaultConfigurationName = Release;
1201 | };
1202 | 52D6DA201BF000BD002C0205 /* Build configuration list for PBXNativeTarget "UAParserSwift-macOS" */ = {
1203 | isa = XCConfigurationList;
1204 | buildConfigurations = (
1205 | 52D6DA211BF000BD002C0205 /* Debug */,
1206 | 52D6DA221BF000BD002C0205 /* Release */,
1207 | );
1208 | defaultConfigurationIsVisible = 0;
1209 | defaultConfigurationName = Release;
1210 | };
1211 | 64CD6C411FAA2175009B4F9A /* Build configuration list for PBXNativeTarget "TestApplication" */ = {
1212 | isa = XCConfigurationList;
1213 | buildConfigurations = (
1214 | 64CD6C3F1FAA2175009B4F9A /* Debug */,
1215 | 64CD6C401FAA2175009B4F9A /* Release */,
1216 | );
1217 | defaultConfigurationIsVisible = 0;
1218 | defaultConfigurationName = Release;
1219 | };
1220 | DD7502821C68FCFC006590AF /* Build configuration list for PBXNativeTarget "UAParserSwift-macOS Tests" */ = {
1221 | isa = XCConfigurationList;
1222 | buildConfigurations = (
1223 | DD7502831C68FCFC006590AF /* Debug */,
1224 | DD7502841C68FCFC006590AF /* Release */,
1225 | );
1226 | defaultConfigurationIsVisible = 0;
1227 | defaultConfigurationName = Release;
1228 | };
1229 | DD7502951C690C7A006590AF /* Build configuration list for PBXNativeTarget "UAParserSwift-tvOS Tests" */ = {
1230 | isa = XCConfigurationList;
1231 | buildConfigurations = (
1232 | DD7502961C690C7A006590AF /* Debug */,
1233 | DD7502971C690C7A006590AF /* Release */,
1234 | );
1235 | defaultConfigurationIsVisible = 0;
1236 | defaultConfigurationName = Release;
1237 | };
1238 | /* End XCConfigurationList section */
1239 | };
1240 | rootObject = 52D6D9731BEFF229002C0205 /* Project object */;
1241 | }
1242 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/project.xcworkspace/xcuserdata/daniele.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malcommac/UAParserSwift/a8057c7cff60db2cdf31d0a0a68ce430754ab64e/UAParserSwift.xcodeproj/project.xcworkspace/xcuserdata/daniele.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/xcshareddata/xcschemes/UAParserSwift-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
64 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/xcshareddata/xcschemes/UAParserSwift-macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
64 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/xcshareddata/xcschemes/UAParserSwift-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
64 |
70 |
71 |
72 |
73 |
79 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/xcshareddata/xcschemes/UAParserSwift-watchOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
44 |
45 |
51 |
52 |
53 |
54 |
60 |
61 |
67 |
68 |
69 |
70 |
72 |
73 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/xcuserdata/daniele.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/UAParserSwift.xcodeproj/xcuserdata/daniele.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | TestApplication.xcscheme
8 |
9 | orderHint
10 | 4
11 |
12 | TestApplication.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 4
16 |
17 | UAParserSwift-iOS.xcscheme_^#shared#^_
18 |
19 | orderHint
20 | 0
21 |
22 | UAParserSwift-macOS.xcscheme_^#shared#^_
23 |
24 | orderHint
25 | 1
26 |
27 | UAParserSwift-tvOS.xcscheme_^#shared#^_
28 |
29 | orderHint
30 | 2
31 |
32 | UAParserSwift-watchOS.xcscheme_^#shared#^_
33 |
34 | orderHint
35 | 3
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malcommac/UAParserSwift/a8057c7cff60db2cdf31d0a0a68ce430754ab64e/banner.png
--------------------------------------------------------------------------------