Defaults read fails with plist and/or nullify tags with System Events

Hi, all. I’ve duplicated two Safari-related plist files to the desktop, and I’m trying to use defaults read to get values from them, however, the shell says one file doesn’t exist.

--Works:
do shell script "defaults read" & " /Users/administrator/Desktop/com.apple.Safari"
--Does not work:
do shell script "defaults read" & " /Users/administrator/Desktop/Cookies" --> "Domain /Users/administrator/Desktop/Cookies does not exist"

Since I can’t use defaults write on the Cookies file, I’ve used System Events to eliminate unwanted items. Setting the value to an empty text sloppily leaves behind tags after the value is cleared, e.g., “”. Setting the value to null leaves a number bounded by integer tags. I would like to strike these tags. Do I have to create a new plist with just the desired entries?

set theList to {}
set theTarget to (path to desktop as text) & "Cookies.plist"

tell application "System Events"
	repeat with propListitem in (property list file (theTarget)'s property list items)
		tell propListitem to try
			set someVar to (get value)'s |Domain|
			if someVar contains "google" then
				set value to "" --???
			else
				set theList's end to someVar
			end if
		end try
	end repeat
end tell

theList

Model: Mac Mini
Browser: Version 4.1.3 (4533.19.4)
Operating System: Mac OS X (10.4)

Hello.

I may be wrong, but “Cookies”, doesn’t seem to be enough to fulfill the standard for a valid domain name.

Maybe I’m very wrong, and if that is the name of the file when you found it, then I have no idea.

But generally a preferences domain starts with com/org/net, then company name, then app or whatever.

As I can remember, a domain name should consist of at least two parts sepearated by dots, on the form; dadida.doah :slight_smile:

Hi Marc.

It seems OK simply to read Safari’s Cookies.plist file. (It’s UTF-8 text.) There’s no need to use “defaults”.

This creates an edited copy of the file and returns a list of the cut entries:

set domain to "google" -- (Escape any characters which have special meanings in regex).

set inPath to quoted form of POSIX path of ((path to desktop as text) & "Cookies.plist")
set outPath to quoted form of POSIX path of ((path to desktop as text) & "Cookies.plist.edit")

set cutDicts to (do shell script ("sed -En '1,/<array>/ w '" & outPath & "'
/<dict>/,/<\\/dict>/ {
	/<dict>/ h
	/<dict>/ !H
	/<\\/dict>/ {
		g
		/<key>Domain<\\/key>[^<]+<string>[^<]*" & domain & "/ s/$/\\'$'\\n''/p
		/\\n$/ !w '" & outPath & "'
	}
}
/<\\/array>/,$ w '" & outPath & "'' " & inPath) without altering line endings)

if ((count cutDicts) is 0) then
	set cutDicts to {}
else
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to linefeed & linefeed
	set cutDicts to text items 1 thru -2 of cutDicts
	set AppleScript's text item delimiters to astid
end if

return cutDicts

The “edited copy” approach above is not only safer than editing the original, but actually necessary with “sed” code which reads lines from a file and writes some of them back to file and some to standard out. If you really need to edit the original and return the cut entries, “sed” can make a backup of the original while editing it, but will have to be be called again to read the relevant entries from the backup:

set domain to "google" -- (Escape any characters which have special meanings in regex).
set inPath to quoted form of POSIX path of ((path to desktop as text) & "Cookies.plist")
set backupPath to quoted form of POSIX path of ((path to desktop as text) & "Cookies.plist.backup")

set cutDicts to (do shell script ("sed -Eni '.backup' '1,/<array>/ p
/<dict>/,/<\\/dict>/ {
	/<dict>/ h
	/<dict>/ !H
	/<\\/dict>/ {
		g
		/<key>Domain<\\/key>[^<]+<string>[^<]*" & domain & "/ !p
	}
}
/<\\/array>/,$ p' " & inPath & " ;
sed -En '/<dict>/,/<\\/dict>/ {
	/<dict>/ h
	/<dict>/ !H
	/<\\/dict>/ {
		g
		/<key>Domain<\\/key>[^<]+<string>[^<]*" & domain & "/ s/$/\\'$'\\n''/p
	}
}' " & backupPath) without altering line endings)

if ((count cutDicts) is 0) then
	set cutDicts to {}
else
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to linefeed & linefeed
	set cutDicts to text items 1 thru -2 of cutDicts
	set AppleScript's text item delimiters to astid
end if

return cutDicts

Thanks, Nigel. It was necessary for me to replace linefeed with “\n” on my machine. I’m not sure if it was your intent, but the first example only returned the entries that should be cut”nothing was actually changed in the file. The second approach worked perfectly. :slight_smile:

An older system, I presume.

Ah. Sorry. I edited that script while posting it and made a small but defeating goof. Now corrected. That script leaves the original file as it was and creates a (now properly) edited copy.