-
-
Save scriptsandthings/f8676400d3bdc9692fe482a4bf075a8b to your computer and use it in GitHub Desktop.
Modify 10.13 (SFL2) Server Favorites list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
""" | |
Merges add_servers into current favorites and removes remove_servers. | |
Run as root to update all users or as normal user to update just that user. | |
""" | |
import os | |
import getpass | |
import subprocess | |
import uuid | |
import Foundation | |
favorites_path = "/Users/{user}/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.FavoriteServers.sfl2" | |
# add these servers if they don't exist already | |
# use a tuple: ("<name>", "<path>") to set a name for the favorite. | |
# otherwise just use a string and the path will be used as the name | |
add_servers = (("My Name", "smb://server.example.com/share"), "vnc://server.example.com") | |
# remove these servers if they exist. Use a wildcard (*) at the end to remove all shares | |
# does not support ("<name>", "<path>") syntax | |
remove_servers = ("smb://old.example.com/*", "vnc://old.example.com") | |
def get_users(): | |
"Get users with a home directory in /Users" | |
# get users from dscl | |
dscl_users = subprocess.check_output(["/usr/bin/dscl", ".", "-list", "/Users"]).splitlines() | |
# get home directories | |
homedir_users = os.listdir("/Users") | |
# return users that are in both lists | |
users = set(dscl_users).intersection(set(homedir_users)) | |
return [u.strip() for u in users if u.strip() != ""] | |
def set_favorites(user, add_servers, remove_servers): | |
"Set the Server Favorites for the given user" | |
# read existing favorites file | |
data = Foundation.NSKeyedUnarchiver.unarchiveObjectWithFile_(favorites_path.format(user=user)) | |
# reformat add_servers to [(name, path), ...] | |
new_add_servers = [] | |
for s in add_servers: | |
if len(s) == 2: | |
new_add_servers.append(s) | |
else: | |
new_add_servers.append((s, s)) | |
add_servers = new_add_servers | |
existing_servers = [] | |
# read existing items safely | |
if data is not None: | |
data_items = data.get("items", []) | |
# read existing servers | |
for item in data_items: | |
name = item["Name"] | |
url, _, _ = Foundation.NSURL.initByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_(Foundation.NSURL.alloc(), item["Bookmark"], Foundation.NSURLBookmarkResolutionWithoutUI, None, None, None) | |
existing_servers.append((name, unicode(url))) | |
# get unique ordered list of all servers | |
all_servers = [] | |
# add existing_servers to list, updating name if necessary | |
for s in existing_servers: | |
try: | |
idx = [a[1] for a in add_servers].index(s[1]) | |
all_servers.append((add_servers[idx][0], s[1])) | |
except ValueError: | |
all_servers.append(s) | |
# add add_servers if not present already | |
for s in add_servers: | |
if s[1] not in [e[1] for e in existing_servers]: | |
all_servers.append(s) | |
# remove old servers: exact match | |
# matches "smb://old.domain" exactly | |
all_servers = [s for s in all_servers if s[1] not in remove_servers] | |
# remove old servers: shares | |
# matches "smb://old.domain/*" | |
all_servers = [s for s in all_servers if len( | |
[True for r in remove_servers if r.endswith("*") and s[1].startswith(r[:-1])] | |
) < 1] | |
# generate necessary structures | |
items = [] | |
for name, path in all_servers: | |
item = {} | |
# use unicode to translate to NSString | |
item["Name"] = unicode(name) | |
url = Foundation.NSURL.URLWithString_(unicode(path)) | |
bookmark, _ = url.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_(0, None, None, None) | |
item["Bookmark"] = bookmark | |
# generate a new UUID for each server | |
item["uuid"] = unicode(uuid.uuid1()).upper() | |
item["visibility"] = 0 | |
item["CustomItemProperties"] = Foundation.NSDictionary.new() | |
items.append(Foundation.NSDictionary.dictionaryWithDictionary_(item)) | |
data = Foundation.NSDictionary.dictionaryWithDictionary_({ | |
"items": Foundation.NSArray.arrayWithArray_(items), | |
"properties": Foundation.NSDictionary.dictionaryWithDictionary_({"com.apple.LSSharedFileList.ForceTemplateIcons": False}) | |
}) | |
# write sfl2 file | |
Foundation.NSKeyedArchiver.archiveRootObject_toFile_(data, favorites_path.format(user=user)) | |
# loop through users and set favorites | |
if __name__ == "__main__": | |
# if running as root, run for all users. Otherwise run for current user | |
user = getpass.getuser() | |
if user == "root": | |
users = get_users() | |
else: | |
users = [user] | |
for user in users: | |
try: | |
set_favorites(user, add_servers, remove_servers) | |
# fix owner if ran as root | |
if user == "root": | |
os.system(("chown {user} " + favorites_path).format(user=user)) | |
print "Server Favorites set for " + user | |
except Exception as e: | |
# if there's an error, log it an continue on | |
print "Failed setting Server Favorites for {0}: {1}".format(user, str(e)) | |
# kill sharedfilelistd process to reload file. Finder should be closed when this happens | |
os.system("killall sharedfilelistd") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
""" | |
Overwrites server favorites with servers. | |
Run as root to update all users or as normal user to update just that user. | |
""" | |
import os | |
import getpass | |
import subprocess | |
import uuid | |
import Foundation | |
favorites_path = "/Users/{user}/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.FavoriteServers.sfl2" | |
# Use a tuple: ("<name>", "<path>") to set a name for the favorite. | |
# Otherwise just use a string and the path will be used as the name | |
servers = (("My Name", "smb://server.example.com/share"), "vnc://server.example.com") | |
def get_users(): | |
"Get users with a home directory in /Users" | |
# get users from dscl | |
dscl_users = subprocess.check_output(["/usr/bin/dscl", ".", "-list", "/Users"]).splitlines() | |
# get home directories | |
homedir_users = os.listdir("/Users") | |
# return users that are in both lists | |
users = set(dscl_users).intersection(set(homedir_users)) | |
return [u.strip() for u in users if u.strip() != ""] | |
def set_favorites(user, servers): | |
"Set the Server Favorites for the given user" | |
# generate necessary structures | |
items = [] | |
for server in servers: | |
name = server[0] if len(server) == 2 else server | |
path = server[1] if len(server) == 2 else server | |
item = {} | |
# use unicode to translate to NSString | |
item["Name"] = unicode(name) | |
url = Foundation.NSURL.URLWithString_(unicode(path)) | |
bookmark, _ = url.bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_(0, None, None, None) | |
item["Bookmark"] = bookmark | |
# generate a new UUID for each server | |
item["uuid"] = unicode(uuid.uuid1()).upper() | |
item["visibility"] = 0 | |
item["CustomItemProperties"] = Foundation.NSDictionary.new() | |
items.append(Foundation.NSDictionary.dictionaryWithDictionary_(item)) | |
data = Foundation.NSDictionary.dictionaryWithDictionary_({ | |
"items": Foundation.NSArray.arrayWithArray_(items), | |
"properties": Foundation.NSDictionary.dictionaryWithDictionary_({"com.apple.LSSharedFileList.ForceTemplateIcons": False}) | |
}) | |
# write sfl2 file | |
Foundation.NSKeyedArchiver.archiveRootObject_toFile_(data, favorites_path.format(user=user)) | |
# loop through users and set favorites | |
if __name__ == "__main__": | |
# if running as root, run for all users. Otherwise run for current user | |
user = getpass.getuser() | |
if user == "root": | |
users = get_users() | |
else: | |
users = [user] | |
for user in users: | |
try: | |
set_favorites(user, servers) | |
# fix owner if ran as root | |
if user == "root": | |
os.system(("chown {user} " + favorites_path).format(user=user)) | |
print "Server Favorites set for " + user | |
except Exception as e: | |
# if there's an error, log it an continue on | |
print "Failed setting Server Favorites for {0}: {1}".format(user, str(e)) | |
# kill sharedfilelistd process to reload file. Finder should be closed when this happens | |
os.system("killall sharedfilelistd") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment