Skip to content

Commit

Permalink
Fix NSSecureCoding implementations
Browse files Browse the repository at this point in the history
@mokagio This should fix the `testPaste{Image,Video}WithoutFormatting` test failures.
 - I have searched the code for `decodeObject(forKey` occurrences and confirmed there wasn't any left
 - But I have not triple-checked that *every* custom subclass of anything we might encode in our `NSAttributedString` attributes have had `+supportsSecureCoding` redefined

Indeed, apparently, **even if** the parent class already overrides it to return `true`, subclasses which override `init?(coder:)`/`encode(with:)` from their parent class need to also re-override `+supportsSecureCoding`. I've added the overrides in classes that I've modified, but there may be more classes that might not be covered by our unit tests around archiving/pasting but would still require it to be added? So would be worth making another pass to be sure we didn't forget any,
  • Loading branch information
AliSoftware committed Apr 18, 2024
1 parent 210f02c commit 665b15b
Show file tree
Hide file tree
Showing 25 changed files with 113 additions and 54 deletions.
4 changes: 2 additions & 2 deletions Aztec/Classes/EditorView/EditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ public class EditorView: UIView {
// MARK: - Initializers

public required init?(coder aDecoder: NSCoder) {
guard let htmlTextView = aDecoder.decodeObject(forKey: EditorView.htmlTextViewKey) as? UITextView,
let richTextView = aDecoder.decodeObject(forKey: EditorView.richTextViewKey) as? TextView else {
guard let htmlTextView = aDecoder.decodeObject(of: UITextView.self, forKey: EditorView.htmlTextViewKey),
let richTextView = aDecoder.decodeObject(of: TextView.self, forKey: EditorView.richTextViewKey) else {
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion Aztec/Classes/Extensions/NSAttributedString+Archive.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extension NSAttributedString
}

static func unarchive(with data: Data) throws -> NSAttributedString? {
return try NSKeyedUnarchiver.unarchivedObject(ofClass: NSAttributedString.self, from: data)
return try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSAttributedString.self, HTMLRepresentation.self], from: data) as? NSAttributedString
}

}
12 changes: 7 additions & 5 deletions Aztec/Classes/Libxml2/DOM/Data/Attribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
/// Represents a basic attribute with no value. This is also the base class for all other
/// attributes.
///
public class Attribute: NSObject, CustomReflectable, NSCoding {
public class Attribute: NSObject, CustomReflectable, NSSecureCoding {

// MARK: - Attribute Definition Properties

Expand Down Expand Up @@ -52,15 +52,15 @@ public class Attribute: NSObject, CustomReflectable, NSCoding {

public required convenience init?(coder aDecoder: NSCoder) {
// TODO: This is a Work in Progress. Let's also get Attribute conforming to Codable!
guard let name = aDecoder.decodeObject(forKey: Keys.name) as? String,
let rawValue = aDecoder.decodeObject(forKey: Keys.value) as? Data,
let value = try? JSONDecoder().decode(Value.self, from: rawValue) else
guard let name = aDecoder.decodeObject(of: NSString.self, forKey: Keys.name),
let rawValue = aDecoder.decodeObject(of: NSData.self, forKey: Keys.value),
let value = try? JSONDecoder().decode(Value.self, from: rawValue as Data) else
{
assertionFailure("Review the logic.")
return nil
}

self.init(name: name, value: value)
self.init(name: name as String, value: value)
}

open func encode(with aCoder: NSCoder) {
Expand All @@ -72,6 +72,8 @@ public class Attribute: NSObject, CustomReflectable, NSCoding {
}
}

public class var supportsSecureCoding: Bool { true }

// MARK: - Equatable

public override func isEqual(_ object: Any?) -> Bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation

/// This enum specifies the different entities that can represent a style in HTML.
///
public class HTMLRepresentation: NSObject, NSCoding {
public class HTMLRepresentation: NSObject, NSSecureCoding {
public enum Kind {
case attribute(Attribute)
case element(HTMLElementRepresentation)
Expand All @@ -24,18 +24,18 @@ public class HTMLRepresentation: NSObject, NSCoding {
}

public required init?(coder aDecoder: NSCoder) {
if let attribute = aDecoder.decodeObject(forKey: Keys.attribute) as? Attribute {
if let attribute = aDecoder.decodeObject(of: Attribute.self, forKey: Keys.attribute) {
kind = .attribute(attribute)
return
}

if let element = aDecoder.decodeObject(forKey: Keys.element) as? HTMLElementRepresentation {
if let element = aDecoder.decodeObject(of: HTMLElementRepresentation.self, forKey: Keys.element) {
kind = .element(element)
return
}

if let rawCSS = aDecoder.decodeObject(forKey: Keys.inline) as? String,
let decodedCSS = CSSAttribute(for: rawCSS) {
if let rawCSS = aDecoder.decodeObject(of: NSString.self, forKey: Keys.inline),
let decodedCSS = CSSAttribute(for: rawCSS as String) {
kind = .inlineCss(decodedCSS)
return
}
Expand All @@ -53,12 +53,14 @@ public class HTMLRepresentation: NSObject, NSCoding {
aCoder.encode(css.toString(), forKey: Keys.inline)
}
}

public class var supportsSecureCoding: Bool { true }
}


// MARK: - HTMLElementRepresentation
//
public class HTMLElementRepresentation: NSObject, CustomReflectable, NSCoding {
public class HTMLElementRepresentation: NSObject, CustomReflectable, NSSecureCoding {
@objc let name: String
@objc let attributes: [Attribute]

Expand All @@ -78,20 +80,30 @@ public class HTMLElementRepresentation: NSObject, CustomReflectable, NSCoding {
// MARK: - NSCoding

public required convenience init?(coder aDecoder: NSCoder) {
guard let name = aDecoder.decodeObject(forKey: #keyPath(name)) as? String,
let attributes = aDecoder.decodeObject(forKey: #keyPath(attributes)) as? [Attribute]
else {
guard let name = aDecoder.decodeObject(of: NSString.self, forKey: #keyPath(name)) else {
fatalError()
}
let decodedAttributes: [Attribute]?

if #available(iOS 14.0, *) {
decodedAttributes = aDecoder.decodeArrayOfObjects(ofClass: Attribute.self, forKey: #keyPath(attributes))
} else {
decodedAttributes = aDecoder.decodeObject(of: NSArray.self, forKey: #keyPath(attributes)) as? [Attribute]
}
guard let attributes = decodedAttributes else {
fatalError()
}

self.init(name: name, attributes: attributes)
self.init(name: name as String, attributes: attributes)
}

open func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: #keyPath(name))
aCoder.encode(attributes, forKey: #keyPath(attributes))
}

public class var supportsSecureCoding: Bool { true }

// MARK: - CustomReflectable

public var customMirror: Mirror {
Expand Down
14 changes: 11 additions & 3 deletions Aztec/Classes/NSAttributedString/Attributes/UnsupportedHTML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation

// MARK: - UnsupportedHTML
//
class UnsupportedHTML: NSObject {
class UnsupportedHTML: NSObject, NSSecureCoding {

/// ElementRepresentation for Unsupported HTML
///
Expand All @@ -18,12 +18,20 @@ class UnsupportedHTML: NSObject {
/// Required Initializers
///
public required init?(coder aDecoder: NSCoder) {
guard let representations = aDecoder.decodeObject(forKey: Keys.representations) as? [HTMLElementRepresentation] else {
return nil
let representations: [HTMLElementRepresentation]?
if #available(iOS 14.0, *) {
representations = aDecoder.decodeArrayOfObjects(ofClass: HTMLElementRepresentation.self, forKey: Keys.representations)
} else {
representations = aDecoder.decodeObject(of: NSArray.self, forKey: Keys.representations) as? [HTMLElementRepresentation]
}

guard let representations else {
return nil
}
self.representations = representations
}

class var supportsSecureCoding: Bool { true }
}


Expand Down
6 changes: 3 additions & 3 deletions Aztec/Classes/TextKit/CommentAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ open class CommentAttachment: NSTextAttachment, RenderableAttachment {
public required init?(coder aDecoder: NSCoder) {
super.init(data: nil, ofType: nil)

guard let text = aDecoder.decodeObject(forKey: Keys.text) as? String else {
guard let text = aDecoder.decodeObject(of: NSString.self, forKey: Keys.text) else {
return
}

self.text = text
self.text = text as String
}


Expand All @@ -48,7 +48,7 @@ open class CommentAttachment: NSTextAttachment, RenderableAttachment {
aCoder.encode(text, forKey: Keys.text)
}


override public class var supportsSecureCoding: Bool { true }

// MARK: - NSTextAttachmentContainer

Expand Down
9 changes: 5 additions & 4 deletions Aztec/Classes/TextKit/HTMLAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,17 @@ open class HTMLAttachment: NSTextAttachment, RenderableAttachment {
public required init?(coder aDecoder: NSCoder) {
super.init(data: nil, ofType: nil)

guard let rootTagName = aDecoder.decodeObject(forKey: Keys.rootTagName) as? String,
let rawHTML = aDecoder.decodeObject(forKey: Keys.rawHTML) as? String
guard let rootTagName = aDecoder.decodeObject(of: NSString.self, forKey: Keys.rootTagName),
let rawHTML = aDecoder.decodeObject(of: NSString.self, forKey: Keys.rawHTML)
else {
return
}

self.rootTagName = rootTagName
self.rawHTML = rawHTML
self.rootTagName = rootTagName as String
self.rawHTML = rawHTML as String
}

override public class var supportsSecureCoding: Bool { true }

/// Extracts the root tag name from a given HTML string
///
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ImageAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ open class ImageAttachment: MediaAttachment {
aCoder.encode(size.rawValue, forKey: EncodeKeys.size.rawValue)
}

override public class var supportsSecureCoding: Bool { true }

private enum EncodeKeys: String {
case alignment
case size
Expand Down
6 changes: 4 additions & 2 deletions Aztec/Classes/TextKit/MediaAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,12 @@ open class MediaAttachment: NSTextAttachment {
///
super.init(coder: aDecoder)

identifier = aDecoder.decodeObject(forKey: EncodeKeys.identifier.rawValue) as? String ?? identifier
url = aDecoder.decodeObject(forKey: EncodeKeys.url.rawValue) as? URL
identifier = aDecoder.decodeObject(of: NSString.self, forKey: EncodeKeys.identifier.rawValue) as? String ?? identifier
url = aDecoder.decodeObject(of: NSURL.self, forKey: EncodeKeys.url.rawValue) as? URL
}

override public class var supportsSecureCoding: Bool { true }

/// Required Initializer
///
override required public init(data contentData: Data?, ofType uti: String?) {
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/Blockquote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class Blockquote: ParagraphProperty {
super.encode(with: aCoder)
}

override public class var supportsSecureCoding: Bool { true }

override public init(with representation: HTMLRepresentation? = nil) {
super.init(with: representation)
}
Expand Down
4 changes: 3 additions & 1 deletion Aztec/Classes/TextKit/ParagraphProperty/Figcaption.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ class Figcaption: ParagraphProperty {
}

required public init?(coder aDecoder: NSCoder){
defaultFont = aDecoder.decodeObject(forKey: CodingKeys.defaultFont) as! UIFont
defaultFont = aDecoder.decodeObject(of: UIFont.self, forKey: CodingKeys.defaultFont)!
super.init(coder: aDecoder)
}

public override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(defaultFont, forKey: CodingKeys.defaultFont)
}

override public class var supportsSecureCoding: Bool { true }
}

private extension Figcaption {
Expand Down
4 changes: 3 additions & 1 deletion Aztec/Classes/TextKit/ParagraphProperty/Figure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ class Figure: ParagraphProperty {
public override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
}


override public class var supportsSecureCoding: Bool { true }

override public init(with representation: HTMLRepresentation? = nil) {
super.init(with: representation)
}
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/HTMLDiv.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class HTMLDiv: ParagraphProperty {
super.encode(with: aCoder)
}

override public class var supportsSecureCoding: Bool { true }

override public init(with representation: HTMLRepresentation? = nil) {
super.init(with: representation)
}
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/HTMLLi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class HTMLLi: ParagraphProperty {
super.encode(with: aCoder)
}

override public class var supportsSecureCoding: Bool { true }

override public init(with representation: HTMLRepresentation? = nil) {
super.init(with: representation)
}
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/HTMLParagraph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class HTMLParagraph: ParagraphProperty {
super.encode(with: aCoder)
}

override public class var supportsSecureCoding: Bool { true }

override public init(with representation: HTMLRepresentation? = nil) {
super.init(with: representation)
}
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/HTMLPre.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ class HTMLPre: ParagraphProperty {
super.encode(with: aCoder)
}

override public class var supportsSecureCoding: Bool { true }

override public init(with representation: HTMLRepresentation? = nil) {
super.init(with: representation)
}
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/Header.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ open class Header: ParagraphProperty {
aCoder.encode(level.rawValue, forKey: Keys.level)
}

override public class var supportsSecureCoding: Bool { true }

static func ==(lhs: Header, rhs: Header) -> Bool {
return lhs.level == rhs.level
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

open class ParagraphProperty: NSObject, NSCoding {
open class ParagraphProperty: NSObject, NSSecureCoding {

open var representation: HTMLRepresentation?

Expand All @@ -19,6 +19,8 @@ open class ParagraphProperty: NSObject, NSCoding {
public func encode(with aCoder: NSCoder) {
}

public class var supportsSecureCoding: Bool { true }

static func ==(lhs: ParagraphProperty, rhs: ParagraphProperty) -> Bool {
return lhs === rhs
}
Expand Down
2 changes: 2 additions & 0 deletions Aztec/Classes/TextKit/ParagraphProperty/TextList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ open class TextList: ParagraphProperty {
aCoder.encode(reversed, forKey: AttributeType.reversed.rawValue)
}

override public class var supportsSecureCoding: Bool { true }

public static func ==(lhs: TextList, rhs: TextList) -> Bool {
return lhs.style == rhs.style && lhs.start == rhs.start && lhs.reversed == rhs.reversed
}
Expand Down
11 changes: 10 additions & 1 deletion Aztec/Classes/TextKit/ParagraphStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,14 @@ open class ParagraphStyle: NSMutableParagraphStyle, CustomReflectable {

public required init?(coder aDecoder: NSCoder) {

if let encodedProperties = aDecoder.decodeObject(forKey:String(describing: ParagraphProperty.self)) as? [ParagraphProperty] {
let encodedProperties: [ParagraphProperty]?
if #available(iOS 14.0, *) {
encodedProperties = aDecoder.decodeArrayOfObjects(ofClass: ParagraphProperty.self, forKey: String(describing: ParagraphProperty.self))
} else {
encodedProperties = aDecoder.decodeObject(of: NSArray.self, forKey: String(describing: ParagraphProperty.self)) as? [ParagraphProperty]
}

if let encodedProperties {
properties = encodedProperties
}

Expand All @@ -105,6 +112,8 @@ open class ParagraphStyle: NSMutableParagraphStyle, CustomReflectable {
aCoder.encode(headerLevel, forKey: EncodingKeys.headerLevel.rawValue)
}

override public class var supportsSecureCoding: Bool { true }

override open func setParagraphStyle(_ baseParagraphStyle: NSParagraphStyle) {

super.setParagraphStyle(baseParagraphStyle)
Expand Down
4 changes: 3 additions & 1 deletion Aztec/Classes/TextKit/VideoAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ open class VideoAttachment: MediaAttachment {
super.init(coder: aDecoder)

if aDecoder.containsValue(forKey: EncodeKeys.posterURL.rawValue) {
posterURL = aDecoder.decodeObject(forKey: EncodeKeys.posterURL.rawValue) as? URL
posterURL = aDecoder.decodeObject(of: NSURL.self, forKey: EncodeKeys.posterURL.rawValue) as? URL
}
}

override public class var supportsSecureCoding: Bool { true }

/// Required Initializer
///
required public init(identifier: String, url: URL?) {
Expand Down

0 comments on commit 665b15b

Please sign in to comment.