Adding Plist data - base64 encoded

imperatives
New Contributor III

I need to add some plist data to com.apple.loginitems.plist as part of a software deploy and have been unable to successfully add the alias data and icon data. If I understand correctly, data is base64 encoded and needs to be decoded before added via plistbuddy. I cannot seem to find any examples and even after the data is decoded it doesn't write to the plist properly. Any ideas?

Thanks!

12 REPLIES 12

mm2270
Legendary Contributor III

If you'r talking about a data formatted field inside a plist. I've run into this as well and came up empty in all my searches. I don't know how the OS writes those data values in to the plist, but its likely using some code/binary under the hood. Not sure how to access that so it writes it in the same way with PlistBuddy. I would love to know how myself,. since I could probably use it from time to time.

Josh_S
Contributor III
plutil -convert xml1 /Users/${username}/Library/Preferences/com.apple.loginitems.plist

To convert it back when you're done, change "xml1" to "binary1".

Edit: Never mind. Just realized that I misunderstood what you were asking. If you're referring to the "Alias" and "Icon" data, I've had some success with just not including that data at all.

mm2270
Legendary Contributor III

@Josh_S, I could be wrong, but I don't think thats what imperatives is referring to. Some entries in plists are stored in a data format, as opposed to the more common ones like string, date, or integer. The "data" ones are very difficult to reproduce with either defaults or Plistbuddy from what I've been able to tell. Maybe I'm just not thinking about it the right way, but whenever I've run across those, I can't ever get the values to write in correctly to the plist using a scripted method. The OS does it somehow of course. but really not sure how.

Josh_S
Contributor III

Yeah, I haven't had my second cup of coffee yet :-)

Just dug this up in another thread:

Add: 

osascript -e 'tell application "System Events" to make login item at end with properties {path:"/path/to/itemname", hidden:false}'

Remove: 

osascript -e 'tell application "System Events" to delete login item "itemname"'

List: 

osascript -e 'tell application "System Events" to get the name of every login item'

imperatives
New Contributor III

I can create the login item path and hidden info via PlistBuddy, but alias <data> is what I am having problems with. When I attempt to write the data info it doesn't seem to add properly. Here is the plist I am attempting to create and the script I am writing to create it.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict> <key>privilegedlist</key> <dict> <key>Controller</key> <string>CustomListItems</string> <key>CustomListItems</key> <array> <dict> <key>Alias</key> <data> AAAAAAC6AAMAAQAAzWj24gAASCsAAAAAAAAASgAKDWMA AMqYC6wAAAAACSD//gAAAAAAAAAA/////wABAAQAAABK AA4AKAATAEEAbABlAHIAdAB1AHMAIABEAGUAcwBrAHQA bwBwAC4AYQBwAHAADwAaAAwATQBhAGMAaQBuAHQAbwBz AGgAIABIAEQAEgAgQXBwbGljYXRpb25zL0FsZXJ0dXMg RGVza3RvcC5hcHAAEwABLwD//wAA </data> <key>CustomItemProperties</key> <dict> <key>com.apple.loginitem.legacyprefs</key> <dict> <key>AliasData</key> <data> AAAAAAC6AAMAAQAAzWj24gAASCsA AAAAAAAASgAKDWMAAMqYC6wAAAAA CSD//gAAAAAAAAAA/////wABAAQA AABKAA4AKAATAEEAbABlAHIAdAB1 AHMAIABEAGUAcwBrAHQAbwBwAC4A YQBwAHAADwAaAAwATQBhAGMAaQBu AHQAbwBzAGgAIABIAEQAEgAgQXBw bGljYXRpb25zL0FsZXJ0dXMgRGVz a3RvcC5hcHAAEwABLwD//wAA </data> <key>Hide</key> <false/> <key>Path</key> <string>/Applications/Alertus Desktop.app</string> </dict> </dict> <key>Icon</key> <data> SW1nUgAAAPQAAAAARkJJTAAAAOgAAAACAAAAAAAAAAAA 2AADAAAAAM1o9uIAAEgrAAAAAAAKDWkACg1sAADKXHns AAAAAAkg//4AAAAAAAAAAP////8AAQAQAAoNaQAKDWQA Cg1jAAAASgAOABoADABBAGwAZQByAHQAdQBzAC4AaQBj AG4AcwAPABoADABNAGEAYwBpAG4AdABvAHMAaAAgAEgA RAASAEBBcHBsaWNhdGlvbnMvQWxlcnR1cyBEZXNrdG9w LmFwcC9Db250ZW50cy9SZXNvdXJjZXMvQWxlcnR1cy5p Y25zABMAAS8A//8AAA== </data> <key>Name</key> <string>Alertus Desktop</string> </dict> </array> </dict>
</dict>
</plist>

Script so far: /usr/libexec/PlistBuddy -c "Add :privilegedlist:Controller string CustomListItems" $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems array" $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:Alias data" $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:CustomItemProperties dict" $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:CustomItemProperties:com.apple.loginitem.HideOnLaunch bool false " $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:CustomItemProperties:com.apple.loginitem.legacyprefs:AliasData data " $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:CustomItemProperties:com.apple.loginitem.legacyprefs:Hide bool false" $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:CustomItemProperties:com.apple.loginitem.legacyprefs:Path string /Applications/Alertus Desktop.app" $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:Icon data " $LoginItemsPlist
/usr/libexec/PlistBuddy -c "Add :privilegedlist:CustomListItems:0:Name string Alertus Desktop" $LoginItemsPlist

imperatives
New Contributor III

@Josh_S
I attempted to leave out the data values, but on login the application will not autolaunch. If I simply take the plist and copy it into the /Library/Preferences folder it does work, but I cannot do this in production since users might have some data already populated there. So it seems like the data values may be necessary. What is most frustrating is that when I decode them they are nothing more then paths to the app with some additional character sprinkled about here and there.

Josh_S
Contributor III

Discovered this, but is seems a little too complicated:
http://blog.magnusviri.com/cfaliasdata-vs-bookmarkdata.html

You could also try the following, using the osascript example in my second post. It does require that they be logged in when deployed, but you could either make this a Self Service item (guaranteeing that they are logged in at the time) or a LaunchDaemon that starts when someone logs in.

#!/bin/sh

loggedInUser=`ls -l /dev/console | awk '{ print $3 }'`
if [[ $loggedInUser != root ]]; then
    echo "User $loggedInUser is logged in..."
    # Get the PID of Dock.app
    loggedInPID=$(ps -axj | awk "/^$loggedInUser/ && /Dock.app/ {print $2;exit}")
    # Create login item via osascript.
    /bin/launchctl bsexec "${loggedInPID}" sudo -iu "${loggedInUser}" "/usr/bin/osascript -e 'tell application "System Events" to make login item at end with properties {path:"/path/to/itemname", hidden:false}'"
else 
    echo "No User logged in..."
fi

As an aside, this whole thing seems to be getting overly complicated. Wouldn't it be easier to just deploy a LaunchAgent to launch whatever you're trying to launch on login?

imperatives
New Contributor III

Josh_S Thanks, I'll give that a shot. It seems like defaults and Plistbuddy have some limitations. Python might be an option, but for simplicity a LaunchAgent seems like the way to go.

mm2270
Legendary Contributor III

I would agree on the LaunchAgent, especially if this is something that you want to set as a requirement for opening upon login, since the other method would only drop an entry into their plist that the user could presumably remove later if they chose to.
A top level LaunchAgent would not be something a non-admin user could remove or disable. (assuming your users are non admins of course)

talkingmoose
Moderator
Moderator

Agree with Mike.

Login items belong to users. Don't try to manipulate user-owned data or you're asking for headaches. Either a launch agent or MCX/Profile should be able to do the trick for most things.

agurley
New Contributor II

Sooo...I'm having the same problem with this datatype. i'm using an AppleScript to make a plist file which includes a license key for this software called Reflector. The license key is of datatype <data>. actually it looks like a really long string, but upon inspection of the original plist it's of type <data>. The script compiles & runs just fine on the client machine, but when I open the app I can't open the Preferences menu (pop up window doesn't appear) and basically the app doesn't work. I checked out the resulting plist file that was created, and everything looks ok except the data type <data> that I told it to use now shows as type <string>. PS, I used to have this working via managed prefs when we were on Casper 8.7, but I recently upgraded to 9.12 and the whole thing got screwed up. I tried creating a new managed preference manually with type "data" however once I scope it and save it, it goes back to type "string" and I'm like whhhhhaaa? Any help out there? I guess there's a way to do this using defaults write so I'll get into that tomorrow.

jdziat
Contributor

agurley - Is there a reason you're avoiding a dmg?