Skip to content

Commit 15d5875

Browse files
committed
Fix quarantineProperty in URLResourceValues
NSURL has an odd behavior around the quarantine dictionary URL resource value - if you want to clear it, you should pass NSNull instead of the NSDictionary. We need to accomodate that in the overlay code with a special case. <rdar://problem/28575806> Cannot remove Quarantine attribute in Swift 3
1 parent d773fa7 commit 15d5875

File tree

2 files changed

+77
-4
lines changed

2 files changed

+77
-4
lines changed

stdlib/public/SDK/Foundation/URL.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,22 @@ public struct URLResourceValues {
287287
/// The quarantine properties as defined in LSQuarantine.h. To remove quarantine information from a file, pass `nil` as the value when setting this property.
288288
@available(OSX 10.10, *)
289289
public var quarantineProperties: [String : Any]? {
290-
get { return _get(.quarantinePropertiesKey) }
291-
set { _set(.quarantinePropertiesKey, newValue: newValue as NSObject?) }
290+
get {
291+
// If a caller has caused us to stash NSNull in the dictionary (via set), make sure to return nil instead of NSNull
292+
if let isNull = _values[.quarantinePropertiesKey] as? NSNull {
293+
return nil
294+
} else {
295+
return _values[.quarantinePropertiesKey] as? [String : Any]
296+
}
297+
}
298+
set {
299+
if let v = newValue {
300+
_set(.quarantinePropertiesKey, newValue: newValue as NSObject?)
301+
} else {
302+
// Set to NSNull, a special case for deleting quarantine properties
303+
_set(.quarantinePropertiesKey, newValue: NSNull())
304+
}
305+
}
292306
}
293307
#endif
294308

test/stdlib/TestURL.swift

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class TestURL : TestURLSuper {
5353
expectTrue(false, "Unable to write data")
5454
}
5555

56-
// Modify an existing resource values
56+
// Modify an existing resource value
5757
do {
5858
var resourceValues = try file.resourceValues(forKeys: [.nameKey])
5959
expectNotNil(resourceValues.name)
@@ -64,9 +64,65 @@ class TestURL : TestURLSuper {
6464
try file.setResourceValues(resourceValues)
6565
} catch {
6666
expectTrue(false, "Unable to set resources")
67-
}
67+
}
6868
}
6969

70+
#if os(OSX)
71+
func testQuarantineProperties() {
72+
// Test the quarantine stuff; it has special logic
73+
if #available(OSX 10.11, iOS 9.0, *) {
74+
// Create a temporary file
75+
var file = URL(fileURLWithPath: NSTemporaryDirectory())
76+
let name = "my_great_file" + UUID().uuidString
77+
file.appendPathComponent(name)
78+
let data = Data(bytes: [1, 2, 3, 4, 5])
79+
do {
80+
try data.write(to: file)
81+
} catch {
82+
expectTrue(false, "Unable to write data")
83+
}
84+
85+
// Set the quarantine info on a file
86+
do {
87+
var resourceValues = URLResourceValues()
88+
resourceValues.quarantineProperties = ["LSQuarantineAgentName" : "TestURL"]
89+
try file.setResourceValues(resourceValues)
90+
} catch {
91+
expectTrue(false, "Unable to set quarantine info")
92+
}
93+
94+
// Get the quarantine info back
95+
do {
96+
var resourceValues = try file.resourceValues(forKeys: [.quarantinePropertiesKey])
97+
expectEqual(resourceValues.quarantineProperties?["LSQuarantineAgentName"] as? String, "TestURL")
98+
} catch {
99+
expectTrue(false, "Unable to get quarantine info")
100+
}
101+
102+
// Clear the quarantine info
103+
do {
104+
var resourceValues = URLResourceValues()
105+
resourceValues.quarantineProperties = nil // this effectively sets a flag
106+
try file.setResourceValues(resourceValues)
107+
108+
// Make sure that the resourceValues property returns nil
109+
expectNil(resourceValues.quarantineProperties)
110+
} catch {
111+
expectTrue(false, "Unable to clear quarantine info")
112+
}
113+
114+
// Get the quarantine info back again
115+
do {
116+
var resourceValues = try file.resourceValues(forKeys: [.quarantinePropertiesKey])
117+
expectNil(resourceValues.quarantineProperties)
118+
} catch {
119+
expectTrue(false, "Unable to get quarantine info after clearing")
120+
}
121+
122+
}
123+
}
124+
#endif
125+
70126
func testMoreSetProperties() {
71127
// Create a temporary file
72128
var file = URL(fileURLWithPath: NSTemporaryDirectory())
@@ -327,6 +383,9 @@ var URLTests = TestSuite("TestURL")
327383
URLTests.test("testBasics") { TestURL().testBasics() }
328384
URLTests.test("testProperties") { TestURL().testProperties() }
329385
URLTests.test("testSetProperties") { TestURL().testSetProperties() }
386+
#if os(OSX)
387+
URLTests.test("testQuarantineProperties") { TestURL().testQuarantineProperties() }
388+
#endif
330389
URLTests.test("testMoreSetProperties") { TestURL().testMoreSetProperties() }
331390
URLTests.test("testURLComponents") { TestURL().testURLComponents() }
332391
URLTests.test("testURLResourceValues") { TestURL().testURLResourceValues() }

0 commit comments

Comments
 (0)