Chris Prince
Chris Prince

Reputation: 7584

iOS `Google` app and sharing extensions getting URL's

I have a sharing extension that accepts URLs. When I use the Google app on iOS, in certain circumstances, it provides a file with a type identifier public.plain-text. However, when I try to decode that as plain text, e.g., using (item below is an NSItemProvider):

        item.loadFileRepresentation(forTypeIdentifier: "public.plain-text") { (url, error) in
            if let error = error {
                logger.error("\(error)")
                return
            }
            
            guard let url = url else {
                logger.error("No url found")
                return
            }
            
            guard let data = try? Data(contentsOf: url) else {
                logger.error("No data loaded from URL")
                return
            }

            guard let string = String(data: data, encoding: .utf8) else {
                logger.error("No string loaded from URL; data.count: \(data.count); \(data)")
                return
            }
            
            logger.debug("string from text file: \(string)")
        }

This fails on the conversation to a .utf8 String.

What is the format of this file? And what does it contain?

Upvotes: 1

Views: 260

Answers (1)

Chris Prince
Chris Prince

Reputation: 7584

I looked at file with an ascii decoding and the first few bytes were bplist00 -- which seems to be a binary plist (e.g, see https://medium.com/@karaiskc/understanding-apples-binary-property-list-format-281e6da00dbd).

Then, I tried decoding the file using:

        item.loadDataRepresentation(forTypeIdentifier: "public.plain-text") { (data, error) in
            if let error = error {
                logger.error("\(error)")
                return
            }

            guard let data = data else {
                logger.error("No data")
                return
            }
            
            guard let plist = try? PropertyListSerialization.propertyList(from: data, format: nil) else {
                logger.error("No data")
                return
            }
            
            let dict = plist as? [String: Any]
            logger.debug("plist: \(plist); dict: \(dict)")
            
            logger.debug("string from text file: \(string)")
        }

Here's the output:

2021-01-12T21:02:18-0700 debug  : plist: {
    "$archiver" = NSKeyedArchiver;
    "$objects" =     (
        "$null",
        "https://www.reddit.com/r/MacOS/comments/kvv21j/macos_malware_used_runonly_applescripts_to_avoid/"
    );
    "$top" =     {
        root = "<CFKeyedArchiverUID 0x28241e5a0 [0x1e7041b20]>{value = 1}";
    };
    "$version" = 100000;
}; dict: Optional(["$archiver": NSKeyedArchiver, "$top": {
    root = "<CFKeyedArchiverUID 0x28241e5a0 [0x1e7041b20]>{value = 1}";
}, "$version": 100000, "$objects": <__NSCFArray 0x283109dc0>(
$null,
https://www.reddit.com/r/MacOS/comments/kvv21j/macos_malware_used_runonly_applescripts_to_avoid/
)
])

So, it looks like I can index into this resulting dictionary and get the URL.

Upvotes: 2

Related Questions