@@ -57,10 +57,11 @@ extension HTTPClient {
57
57
guard !trimmedName. isEmpty else {
58
58
return nil
59
59
}
60
+
60
61
// FIXME: The parsed values should be validated to ensure they only contain ASCII characters allowed by RFC-6265.
61
62
// https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1
62
- self . name = String ( utf8Slice : trimmedName, in : header )
63
- self . value = String ( utf8Slice : trimmedValue. trimmingPairedASCIIQuote ( ) , in : header )
63
+ self . name = String ( aligningUTF8 : trimmedName)
64
+ self . value = String ( aligningUTF8 : trimmedValue. trimmingPairedASCIIQuote ( ) )
64
65
self . path = " / "
65
66
self . domain = defaultDomain
66
67
self . expires_timestamp = nil
@@ -71,11 +72,11 @@ extension HTTPClient {
71
72
for component in components {
72
73
switch component. parseCookieComponent ( ) {
73
74
case ( " path " , . some( let value) ) ? :
74
- self . path = String ( utf8Slice : value, in : header )
75
+ self . path = String ( aligningUTF8 : value)
75
76
case ( " domain " , . some( let value) ) ? :
76
- self . domain = String ( utf8Slice : value, in : header )
77
+ self . domain = String ( aligningUTF8 : value)
77
78
case ( " expires " , . some( let value) ) ? :
78
- self . expires_timestamp = parseCookieTime ( value, in : header )
79
+ self . expires_timestamp = parseCookieTime ( value)
79
80
case ( " max-age " , . some( let value) ) ? :
80
81
self . maxAge = Int ( Substring ( value) )
81
82
case ( " secure " , nil ) ? :
@@ -121,8 +122,8 @@ extension HTTPClient.Response {
121
122
122
123
extension String {
123
124
/// Creates a String from a slice of UTF8 code-units, aligning the bounds to unicode scalar boundaries if needed.
124
- fileprivate init ( utf8Slice: String . UTF8View . SubSequence , in base : String ) {
125
- self . init ( base [ utf8Slice. startIndex ..< utf8Slice . endIndex ] )
125
+ fileprivate init ( aligningUTF8 utf8Slice: String . UTF8View . SubSequence ) {
126
+ self . init ( Substring ( utf8Slice) )
126
127
}
127
128
}
128
129
@@ -176,33 +177,30 @@ private let posixLocale: UnsafeMutableRawPointer = {
176
177
return UnsafeMutableRawPointer ( _posixLocale)
177
178
} ( )
178
179
179
- private func parseTimestamp( _ string : String , format: String ) -> tm ? {
180
+ private func parseTimestamp( _ utf8 : String . UTF8View . SubSequence , format: String ) -> tm ? {
180
181
var timeComponents = tm ( )
181
- guard swiftahc_cshims_strptime_l ( string , format , & timeComponents , posixLocale ) else {
182
- return nil
182
+ let success = Substring ( utf8 ) . withCString { cString in
183
+ swiftahc_cshims_strptime_l ( cString , format , & timeComponents , posixLocale )
183
184
}
184
- return timeComponents
185
+ return success ? timeComponents : nil
185
186
}
186
187
187
- private func parseCookieTime( _ timestampUTF8: String . UTF8View . SubSequence , in header : String ) -> Int64 ? {
188
+ private func parseCookieTime( _ timestampUTF8: String . UTF8View . SubSequence ) -> Int64 ? {
188
189
if timestampUTF8. contains ( where: { $0 < 0x20 /* Control characters */ || $0 == 0x7F /* DEL */ } ) {
189
190
return nil
190
191
}
191
- let timestampString : String
192
+ var timestampUTF8 = timestampUTF8
192
193
if timestampUTF8. hasSuffix ( " GMT " . utf8) {
193
194
let timezoneStart = timestampUTF8. index ( timestampUTF8. endIndex, offsetBy: - 3 )
194
- let trimmedTimestampUTF8 = timestampUTF8 [ ..< timezoneStart] . trimmingASCIISpaces ( )
195
- guard trimmedTimestampUTF8 . endIndex != timezoneStart else {
195
+ timestampUTF8 = timestampUTF8 [ ..< timezoneStart] . trimmingASCIISpaces ( )
196
+ guard timestampUTF8 . endIndex != timezoneStart else {
196
197
return nil
197
198
}
198
- timestampString = String ( utf8Slice: trimmedTimestampUTF8, in: header)
199
- } else {
200
- timestampString = String ( utf8Slice: timestampUTF8, in: header)
201
199
}
202
200
guard
203
- var timeComponents = parseTimestamp ( timestampString , format: " %a, %d %b %Y %H:%M:%S " )
204
- ?? parseTimestamp ( timestampString , format: " %a, %d-%b-%y %H:%M:%S " )
205
- ?? parseTimestamp ( timestampString , format: " %a %b %d %H:%M:%S %Y " )
201
+ var timeComponents = parseTimestamp ( timestampUTF8 , format: " %a, %d %b %Y %H:%M:%S " )
202
+ ?? parseTimestamp ( timestampUTF8 , format: " %a, %d-%b-%y %H:%M:%S " )
203
+ ?? parseTimestamp ( timestampUTF8 , format: " %a %b %d %H:%M:%S %Y " )
206
204
else {
207
205
return nil
208
206
}
0 commit comments