@@ -95,8 +95,23 @@ public let NSHTTPCookiePort: String = "Port"
95
95
attributes of a cookie.
96
96
*/
97
97
public class NSHTTPCookie : NSObject {
98
- var _properties : [ String : AnyObject ]
99
-
98
+ private struct Cookie {
99
+ let comment : String ?
100
+ let commentURL : NSURL ?
101
+ let domain : String
102
+ let expiresDate : NSDate ?
103
+ let HTTPOnly : Bool
104
+ let secure : Bool
105
+ let sessionOnly : Bool
106
+ let name : String
107
+ let path : String
108
+ let portList : [ NSNumber ] ?
109
+ let properties : [ String : Any ] ?
110
+ let value : String
111
+ let version : Int
112
+ }
113
+ private let cookieRepresentation : Cookie
114
+
100
115
/*!
101
116
@method initWithProperties:
102
117
@abstract Initialize a NSHTTPCookie object with a dictionary of
@@ -220,20 +235,121 @@ public class NSHTTPCookie : NSObject {
220
235
dictionary keys is invalid, for example because a required key is
221
236
missing, or a recognized key maps to an illegal value.
222
237
*/
223
- public init ? ( properties: [ String : AnyObject ] ) {
224
- func isValidProperty( property: String ? ) -> Bool {
225
- if let propertyValue = property {
226
- return propertyValue. length > 0 && ( propertyValue as NSString ) . rangeOfString ( " /n " ) . location == NSNotFound
238
+ /// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative
239
+ /// - Note: Since this API is under consideration it may be either removed or revised in the near future
240
+ public init? ( properties: [ String : Any ] ) {
241
+ guard let
242
+ path = properties [ NSHTTPCookiePath] as? String ,
243
+ name = properties [ NSHTTPCookieName] as? String ,
244
+ value = properties [ NSHTTPCookieValue] as? String
245
+ else {
246
+ return nil
247
+ }
248
+
249
+ let canonicalDomain : String
250
+ if let domain = properties [ NSHTTPCookieDomain] as? String {
251
+ canonicalDomain = domain
252
+ } else if let
253
+ originURL = properties [ NSHTTPCookieOriginURL] as? NSURL ,
254
+ host = originURL. host
255
+ {
256
+ canonicalDomain = host
257
+ } else {
258
+ return nil
259
+ }
260
+
261
+ let secure: Bool
262
+ if let
263
+ secureString = properties [ NSHTTPCookieSecure] as? String
264
+ where secureString. characters. count > 0
265
+ {
266
+ secure = true
267
+ } else {
268
+ secure = false
269
+ }
270
+
271
+ let version: Int
272
+ if let
273
+ versionString = properties [ NSHTTPCookieSecure] as? String
274
+ where versionString == " 1 "
275
+ {
276
+ version = 1
277
+ } else {
278
+ version = 0
279
+ }
280
+
281
+ let portList: [ NSNumber] ?
282
+ if let portString = properties [ NSHTTPCookiePort] as? String {
283
+ portList = portString. characters
284
+ . split ( " , " )
285
+ . flatMap { Int ( String ( $0) ) }
286
+ . map { NSNumber ( integer: $0) }
287
+ } else {
288
+ portList = nil
289
+ }
290
+
291
+ // TODO: factor into a utility function
292
+ let expiresDate: NSDate?
293
+ if version == 0 {
294
+ let expiresProperty = properties [ NSHTTPCookieExpires]
295
+ if let date = expiresProperty as? NSDate {
296
+ // If the dictionary value is already an NSDate,
297
+ // nothing left to do
298
+ expiresDate = date
299
+ } else if let dateString = expiresProperty as? String {
300
+ // If the dictionary value is a string, parse it
301
+ let formatter = NSDateFormatter ( )
302
+ formatter. dateFormat = " yyyy-MM-dd'T'HH:mm "
303
+
304
+ let timeZone = NSTimeZone ( abbreviation: " GMT " )
305
+ formatter. timeZone = timeZone
306
+
307
+ expiresDate = formatter. dateFromString ( dateString)
308
+ } else {
309
+ expiresDate = nil
310
+ }
311
+ } else if version == 1 {
312
+ if let
313
+ maximumAge = properties [ NSHTTPCookieMaximumAge] as? String ,
314
+ secondsFromNow = Double ( maximumAge)
315
+ {
316
+ expiresDate = NSDate ( timeIntervalSinceNow: secondsFromNow)
317
+ } else {
318
+ expiresDate = nil
227
319
}
228
- return false
320
+ } else {
321
+ expiresDate = nil
229
322
}
230
- if !isValidProperty( properties [ NSHTTPCookiePath] as? String )
231
- || !isValidProperty( properties [ NSHTTPCookieDomain] as? String )
232
- || !isValidProperty( properties [ NSHTTPCookieName] as? String )
233
- || !isValidProperty( properties [ NSHTTPCookieValue] as? String ) {
234
- return nil
323
+
324
+ var discard = false
325
+ if let discardString = properties [ NSHTTPCookieDiscard] as? String {
326
+ discard = discardString == " TRUE "
327
+ } else if let
328
+ _ = properties [ NSHTTPCookieMaximumAge] as? String
329
+ where version >= 1
330
+ {
331
+ discard = false
235
332
}
236
- _properties = properties
333
+
334
+ // TODO: commentURL can be a string or NSURL
335
+
336
+ self. cookieRepresentation = Cookie (
337
+ comment: version == 1 ?
338
+ properties [ NSHTTPCookieComment] as? String : nil ,
339
+ commentURL: version == 1 ?
340
+ properties [ NSHTTPCookieCommentURL] as? NSURL : nil ,
341
+ domain: canonicalDomain,
342
+ expiresDate: expiresDate,
343
+ HTTPOnly: secure,
344
+ secure: secure,
345
+ sessionOnly: discard,
346
+ name: name,
347
+ path: path,
348
+ portList: version == 1 ? portList : nil ,
349
+ properties: properties,
350
+ value: value,
351
+ version: version
352
+ )
237
353
}
238
354
239
355
/*!
@@ -258,7 +374,17 @@ public class NSHTTPCookie : NSObject {
258
374
@result An NSDictionary where the keys are header field names, and the values
259
375
are the corresponding header field values.
260
376
*/
261
- public class func requestHeaderFieldsWithCookies( cookies: [ NSHTTPCookie ] ) -> [ String : String ] { NSUnimplemented ( ) }
377
+ public class func requestHeaderFieldsWithCookies( cookies: [ NSHTTPCookie] ) - > [ String : String] {
378
+ var cookieString = cookies. reduce ( " " ) { ( sum, next) -> String in
379
+ return sum + " \( next. cookieRepresentation. name) = \( next. cookieRepresentation. value) ; "
380
+ }
381
+ //Remove the final trailing semicolon and whitespace
382
+ if ( cookieString. length > 0 ) {
383
+ cookieString. removeAtIndex ( cookieString. endIndex. predecessor ( ) )
384
+ cookieString. removeAtIndex ( cookieString. endIndex. predecessor ( ) )
385
+ }
386
+ return [ " Cookie " : cookieString]
387
+ }
262
388
263
389
/*!
264
390
@method cookiesWithResponseHeaderFields:forURL:
@@ -283,8 +409,10 @@ public class NSHTTPCookie : NSObject {
283
409
for descriptions of the supported keys and values.
284
410
@result The dictionary representation of the receiver.
285
411
*/
286
- public var properties : [ String : AnyObject ] ? {
287
- return _properties
412
+ /// - Experiment: This is a draft API currently under consideration for official import into Foundation as a suitable alternative
413
+ /// - Note: Since this API is under consideration it may be either removed or revised in the near future
414
+ public var properties: [ String : Any] ? {
415
+ return self . cookieRepresentation. properties
288
416
}
289
417
290
418
/*!
@@ -295,7 +423,7 @@ public class NSHTTPCookie : NSObject {
295
423
@result the version of the receiver.
296
424
*/
297
425
public var version: Int {
298
- return ( _properties [ NSHTTPCookieVersion ] as! Int )
426
+ return self . cookieRepresentation . version
299
427
}
300
428
301
429
/*!
@@ -304,7 +432,7 @@ public class NSHTTPCookie : NSObject {
304
432
@result the name of the receiver.
305
433
*/
306
434
public var name: String {
307
- return ( _properties [ NSHTTPCookieName ] as! NSString ) . _swiftObject
435
+ return self . cookieRepresentation . name
308
436
}
309
437
310
438
/*!
@@ -313,7 +441,7 @@ public class NSHTTPCookie : NSObject {
313
441
@result the value of the receiver.
314
442
*/
315
443
public var value: String {
316
- return ( _properties [ NSHTTPCookieValue ] as! NSString ) . _swiftObject
444
+ return self . cookieRepresentation . value
317
445
}
318
446
319
447
/*!
@@ -326,10 +454,7 @@ public class NSHTTPCookie : NSObject {
326
454
@result The expires date of the receiver.
327
455
*/
328
456
/*@NSCopying*/ public var expiresDate: NSDate? {
329
- if let expiresDate = _properties [ NSHTTPCookieExpires] as? NSDate {
330
- return expiresDate
331
- }
332
- return nil
457
+ return self . cookieRepresentation. expiresDate
333
458
}
334
459
335
460
/*!
@@ -340,7 +465,7 @@ public class NSHTTPCookie : NSObject {
340
465
be discarded at the end of the session.
341
466
*/
342
467
public var sessionOnly: Bool {
343
- return ! ( _properties [ NSHTTPCookieExpires ] is NSDate )
468
+ return self . cookieRepresentation . sessionOnly
344
469
}
345
470
346
471
/*!
@@ -353,7 +478,7 @@ public class NSHTTPCookie : NSObject {
353
478
@result The domain of the receiver.
354
479
*/
355
480
public var do main: String {
356
- return ( _properties [ NSHTTPCookieDomain ] as! NSString ) . _swiftObject
481
+ return self . cookieRepresentation . domain
357
482
}
358
483
359
484
/*!
@@ -365,7 +490,7 @@ public class NSHTTPCookie : NSObject {
365
490
@result The path of the receiver.
366
491
*/
367
492
public var path: String {
368
- return ( _properties [ NSHTTPCookiePath ] as! NSString ) . _swiftObject
493
+ return self . cookieRepresentation . path
369
494
}
370
495
371
496
/*!
@@ -379,7 +504,9 @@ public class NSHTTPCookie : NSObject {
379
504
@result YES if this cookie should be sent only over secure channels,
380
505
NO otherwise.
381
506
*/
382
- public var secure : Bool { NSUnimplemented ( ) }
507
+ public var secure: Bool {
508
+ return self . cookieRepresentation. secure
509
+ }
383
510
384
511
/*!
385
512
@method isHTTPOnly
@@ -393,7 +520,9 @@ public class NSHTTPCookie : NSObject {
393
520
@result YES if this cookie should only be sent via HTTP headers,
394
521
NO otherwise.
395
522
*/
396
- public var HTTPOnly : Bool { NSUnimplemented ( ) }
523
+ public var HTTPOnly: Bool {
524
+ return self . cookieRepresentation. HTTPOnly
525
+ }
397
526
398
527
/*!
399
528
@method comment
@@ -405,7 +534,7 @@ public class NSHTTPCookie : NSObject {
405
534
comment.
406
535
*/
407
536
public var comment: String? {
408
- return ( _properties [ NSHTTPCookieComment ] as! NSString ) . _swiftObject
537
+ return self . cookieRepresentation . comment
409
538
}
410
539
411
540
/*!
@@ -418,10 +547,7 @@ public class NSHTTPCookie : NSObject {
418
547
has no comment URL.
419
548
*/
420
549
/*@NSCopying*/ public var commentURL: NSURL? {
421
- if let commentURL = _properties [ NSHTTPCookieCommentURL] as? NSURL {
422
- return commentURL
423
- }
424
- return nil
550
+ return self . cookieRepresentation. commentURL
425
551
}
426
552
427
553
/*!
@@ -435,6 +561,8 @@ public class NSHTTPCookie : NSObject {
435
561
array may be nil, in which case this cookie can be sent to any
436
562
port.
437
563
*/
438
- public var portList : [ NSNumber ] ? { NSUnimplemented ( ) }
564
+ public var portList: [ NSNumber] ? {
565
+ return self . cookieRepresentation. portList
566
+ }
439
567
}
440
568
0 commit comments