Skip to content

Commit 04616a3

Browse files
committed
correct user-agent parser bug
1 parent dbbe641 commit 04616a3

File tree

6 files changed

+65
-33
lines changed

6 files changed

+65
-33
lines changed

Sources/SwiftinitServer/Server/Swiftinit.ClientAnnotation.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,35 +147,35 @@ extension Swiftinit.ClientAnnotation
147147
suspicion -= 100
148148
}
149149

150-
case .single("AppleWebKit", let version?):
150+
case .single("AppleWebKit", .numeric(let version, _)?):
151151
// Modern WebKit version: might be a Barbie.
152-
if version.major >= 604
152+
if version >= 604
153153
{
154154
suspicion -= 1
155155
}
156156

157-
case .single("Firefox", let version?):
157+
case .single("Firefox", .numeric(let version, _)?):
158158
// Modern Firefox version: might be a Barbie.
159-
if version.major >= 115
159+
if version >= 115
160160
{
161161
suspicion -= 1
162162
}
163163

164-
case .single("CriOS", let version?):
164+
case .single("CriOS", .numeric(let version, _)?):
165165
// Modern Chrome version: might be a Barbie.
166-
if version.major >= 109
166+
if version >= 109
167167
{
168168
suspicion -= 1
169169
}
170170

171-
case .single("Chrome", let version?):
171+
case .single("Chrome", .numeric(let version, _)?):
172172
// Modern Chrome version: might be a Barbie.
173-
if version.major >= 109
173+
if version >= 109
174174
{
175175
suspicion -= 1
176176
}
177177
// Very old Chrome version: probably a bot.
178-
if version.major < 90
178+
if version < 90
179179
{
180180
suspicion += 10
181181
}

Sources/UA/Parser/UA.VersionRule.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@ extension UA.VersionRule:ParsingRule
1717
where Source:Collection<UInt8>, Source.Index == Location
1818
{
1919
try input.parse(as: UnicodeEncoding.Slash.self)
20-
let major:Int = try input.parse(
21-
as: Pattern.UnsignedInteger<UnicodeDigit<Location, Terminal, Int>.Decimal>.self)
2220

23-
if let _:Void = input.parse(as: UnicodeEncoding.Period?.self)
21+
if let (major, _):(Int, Void) = try? input.parse(as:
22+
(
23+
Pattern.UnsignedInteger<UnicodeDigit<Location, Terminal, Int>.Decimal>,
24+
UnicodeEncoding.Period
25+
).self)
2426
{
25-
return .init(major: major, minor: try input.parse(as: UA.NameRule.self))
27+
return .numeric(major, try input.parse(as: UA.NameRule.self))
2628
}
2729
else
2830
{
29-
return .init(major: major, minor: nil)
31+
return .nominal(try input.parse(as: UA.NameRule.self))
3032
}
3133
}
3234
}

Sources/UA/UA.Component.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extension UA.Component
1414
@inlinable public static
1515
func single(_ name:String, _ major:Int, _ minor:String? = nil) -> Self
1616
{
17-
.single(name, .init(major: major, minor: minor))
17+
.single(name, .numeric(major, minor))
1818
}
1919

2020
@inlinable public static

Sources/UA/UA.Version.swift

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
extension UA
22
{
33
@frozen public
4-
struct Version:Equatable, Hashable, Sendable
4+
enum Version:Equatable, Hashable, Sendable
55
{
6-
public
7-
let major:Int
8-
public
9-
let minor:String?
10-
11-
@inlinable public
12-
init(major:Int, minor:String? = nil)
6+
case numeric(Int, String?)
7+
case nominal(String)
8+
}
9+
}
10+
extension UA.Version
11+
{
12+
@inlinable public
13+
var major:Int?
14+
{
15+
switch self
1316
{
14-
self.major = major
15-
self.minor = minor
17+
case .numeric(let major, _): major
18+
case .nominal: nil
1619
}
1720
}
1821
}
@@ -21,6 +24,11 @@ extension UA.Version:CustomStringConvertible
2124
@inlinable public
2225
var description:String
2326
{
24-
self.minor.map { "\(self.major).\($0)" } ?? "\(self.major)"
27+
switch self
28+
{
29+
case .numeric(let major, let suffix?): "\(major).\(suffix)"
30+
case .numeric(let major, nil): "\(major)"
31+
case .nominal(let name): name
32+
}
2533
}
2634
}

Sources/UA/UA.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ extension UA:CustomStringConvertible
5151
}
5252
extension UA:LosslessStringConvertible
5353
{
54+
public
55+
init(parsing description:String) throws
56+
{
57+
self.init(components: try ParsingRule.parse(description.utf8))
58+
}
59+
5460
public
5561
init?(_ description:String)
5662
{

Sources/UATests/Main.Parsing.swift

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ extension Main
99
{
1010
}
1111
}
12+
13+
import Grammar
14+
1215
extension Main.Parsing:TestBattery
1316
{
1417
private static
@@ -23,13 +26,26 @@ extension Main.Parsing:TestBattery
2326
static
2427
func run(tests:TestGroup)
2528
{
26-
// TODO
27-
let _:String = """
28-
Mozilla/5.0 (iPhone; CPU iPhone OS 17_1_2 like Mac OS X) \
29-
AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1.2 Mobile/15E148 Safari/604.1
30-
"""
31-
32-
if let tests:TestGroup = tests / "SafariWithPrivacyGuard"
29+
if let tests:TestGroup = tests / "iPhoneSafari"
30+
{
31+
Self.run(tests,
32+
parsing: """
33+
Mozilla/5.0 (iPhone; CPU iPhone OS 17_1_2 like Mac OS X) \
34+
AppleWebKit/605.1.15 (KHTML, like Gecko) \
35+
Version/17.1.2 Mobile/15E148 Safari/604.1
36+
""",
37+
expected:
38+
[
39+
.single("Mozilla", 5, "0"),
40+
.group("iPhone", "CPU iPhone OS 17_1_2 like Mac OS X"),
41+
.single("AppleWebKit", 605, "1.15"),
42+
.group("KHTML, like Gecko"),
43+
.single("Version", 17, "1.2"),
44+
.single("Mobile", .nominal("15E148")),
45+
.single("Safari", 604, "1"),
46+
])
47+
}
48+
if let tests:TestGroup = tests / "macSafariWithPrivacyGuard"
3349
{
3450
Self.run(tests,
3551
parsing: """

0 commit comments

Comments
 (0)