Skip to content

Instantly share code, notes, and snippets.

@guozheng
Created October 10, 2011 00:54
Show Gist options
  • Save guozheng/1274427 to your computer and use it in GitHub Desktop.
Save guozheng/1274427 to your computer and use it in GitHub Desktop.
Comcast add bookmarks Ruby script
#!/usr/bin/ruby
# a script to add some bookmarks, loaded from an xml file
require "rexml/document"
require "json"
require "plist"
require "fileutils"
##################
# helper functions
##################
def write_number_as_two_digits(fixnum)
str = ""
if (fixnum < 10)
str = "0"+fixnum.to_s
else
str = fixnum.to_s
end
return str
end
##################
# Begin Script
##################
puts "\n\n\n----------------------------\n"
puts "Begin add_bookmarks ruby script "+Time.now.to_s
puts "version "+`cat version`
puts "----------------------------\n"
originalDirectory = File.dirname(File.expand_path($0))
puts "script running from "+originalDirectory+"\n\n"
abs_path_to_utils = originalDirectory
if (ARGV[0] != nil)
abs_path_to_utils = ARGV[0]
end
##
## Kill existing browser processes
##
safariPID = `ps ux -w -w | awk '/Safari.app/ && !/awk/ {print $2}'`
puts "safari PID = "+safariPID
if (safariPID != "" && safariPID != nil)
puts "killing Safari"
`kill #{safariPID.to_s}`
`sleep 2`
end
firefoxPID = `ps ux -w -w | awk '/Firefox.app/ && !/awk/ {print $2}'`
puts "firefox PID = "+firefoxPID
if (firefoxPID != "" && firefoxPID != nil)
puts "killing Firefox"
`kill #{firefoxPID.to_s}`
`sleep 2`
end
chromePIDs = `ps ux -w -w | awk '/Chrome.app/ && !/awk/ {print $2}'`
chromeOpened = false
puts "chrome PID = "+chromePIDs
chromePIDArray = chromePIDs.split("\n")
chromePIDArray.each { |pid|
if (pid != "" && pid != nil)
puts "killing chrome process "+pid
`kill #{pid.to_s}`
chromeOpened=true
end
}
if chromeOpened
`sleep 2`
end
# load an xml file of the bookmarks
#
prefsXml = File.new("comcast_prefs.xml")
doc = REXML::Document.new(prefsXml)
bookmarksArray = []
homepage = REXML::Text.read_with_substitution(doc.get_elements("document/homepage/url")[0].get_text().to_s())
# homepage is special, and requires an appended parameter to representing the install date
now = Time.now
homepage = homepage + "&cid=insDate"+write_number_as_two_digits(now.month)+write_number_as_two_digits(now.day)+now.year.to_s
searchProviderName = REXML::Text.read_with_substitution(doc.get_elements("document/searchProvider/title")[0].get_text().to_s())
searchProviderUrl = REXML::Text.read_with_substitution(doc.get_elements("document/searchProvider/searchUrl")[0].get_text().to_s())
searchProviderHomepage = REXML::Text.read_with_substitution(doc.get_elements("document/searchProvider/homepageUrl")[0].get_text().to_s())
Dir.chdir() do
doc.get_elements("document/desktopShortcut").each { |shortcutNode|
titleString = shortcutNode.get_elements("title")[0].get_text().to_s()
urlString = REXML::Text.read_with_substitution(shortcutNode.get_elements("url")[0].get_text().to_s())
iconString = shortcutNode.get_elements("icon")[0].get_text().to_s()
f = File.new("Desktop/#{titleString}.url","w")
f.write("[InternetShortcut]\nURL="+urlString+"\n")
f.close
puts `"#{abs_path_to_utils}/setfileicon" "#{abs_path_to_utils}/#{iconString}" "#{f.path}"`
puts `"#{abs_path_to_utils}/setfile" -a E "#{f.path}"`
}
end
successURL = doc.get_elements("document/successURL")[0].get_text().to_s()
f = File.new(abs_path_to_utils+"/successurl","w")
f.write(successURL)
prefsXml.close
# build an array of all the bookmark objects
doc.elements.each("document/bookmark") {|element|
bookmark = {}
bookmark["title"] = REXML::Text.read_with_substitution(element.get_elements("title")[0].get_text().to_s())
bookmark["url"] = REXML::Text.read_with_substitution(element.get_elements("url")[0].get_text().to_s())
bookmarksArray.push(bookmark)
}
# debug:
#
puts "\nhomepage - "+homepage
puts "\nsearch: "+searchProviderName+" - "+searchProviderUrl
bookmarksArray.each {|bookmark|
puts "\n"
puts bookmark["title"]+" - "+bookmark["url"]
}
##############
# Chrome
##############
#relative to ~/
CHROME_PREFERENCE_LOCATION = "Library/Application Support/Google/Chrome/Default/Preferences"
CHROME_BOOKMARK_LOCATION = "Library/Application Support/Google/Chrome/Default/Bookmarks"
print "\n\nBegin Chrome Operations\n"
# load the bookmarks json file
Dir.chdir() do
if (File.exist?CHROME_BOOKMARK_LOCATION)
bm_file = File.new(CHROME_BOOKMARK_LOCATION, "r")
parsedChromeBookmarks = JSON.parse(bm_file.readlines.to_s)
bm_file.close
folder = {}
folder["name"] = "XFINITY"
folder["type"] = "folder"
folder["children"] = []
bookmarksArray.each { |bookmark|
bm = {}
bm["name"] = bookmark["title"]
bm["type"] = "url"
bm["url"] = bookmark["url"]
folder["children"].push(bm)
}
#search through the existing and see if there's already a "Comcast Xfinity" folder
a = parsedChromeBookmarks["roots"]["bookmark_bar"]["children"]
i = a.length-1
while i > -1
if a[i]["name"] == "Comcast Xfinity"
a.delete_at(i)
end
i -= 1
end
parsedChromeBookmarks["roots"]["bookmark_bar"]["children"].unshift(folder)
bm_file = File.new(CHROME_BOOKMARK_LOCATION,"w")
bm_file.write(JSON.pretty_generate(parsedChromeBookmarks))
bm_file.close
else
puts "cannot find chrome bookmarks file"
end
if (File.exist?CHROME_PREFERENCE_LOCATION)
pref_file = File.new(CHROME_PREFERENCE_LOCATION,"r")
parsedPrefs = JSON.parse(pref_file.readlines.to_s)
pref_file.close
#homepage
parsedPrefs["homepage"] = homepage
# #search provider (doesn't seem to work)
# sn = {
# "enabled"=>true,
# "encodings"=>"",
# "icon_url"=>"",
# "instant_url"=>"",
# "keyword"=>"comcast",
# "name"=>"comcast.net",
# "prepopulate_id"=>"0",
# "search_url"=>searchProviderUrl+"{searchTerms}",
# "suggest_url"=>""
# }
# parsedPrefs["default_search_provider"] = sn
pref_file = File.new(CHROME_PREFERENCE_LOCATION,"w")
pref_file.write(JSON.pretty_generate(parsedPrefs))
pref_file.close
else
puts "cannot find chrome preferences files"
end
end
##############
# Safari
##############
SAFARI_BOOKMARKS_LOCATION = "Library/Safari/Bookmarks.plist"
SAFARI_PREFERENCES_LOCATION = "Library/Preferences/com.apple.Safari.plist"
SAFARI_CONFIGURATION_LOCATION = "Library/Safari/Configurations.plist.signed"
Dir.chdir() do
##
## Bookmarks
##
if (File.exist?(SAFARI_BOOKMARKS_LOCATION))
if (system 'plutil -convert xml1 '+SAFARI_BOOKMARKS_LOCATION)
# bm_file = File.new(SAFARI_BOOKMARKS_LOCATION,"r")
parsedBm = Plist::parse_xml(SAFARI_BOOKMARKS_LOCATION)
barFolder = nil
parsedBm["Children"].each { |folder|
if (folder["Title"] == "BookmarksBar")
barFolder = folder
break
end
}
if barFolder != nil
if barFolder["Children"] == nil
barFolder["Children"] = []
end
puts "Items on BookmarksBar: "+barFolder["Children"].length.to_s
# search for an existing "Comcast Xfinity" folder
i = barFolder["Children"].length-1
while i > -1
if barFolder["Children"][i]["Title"] == "Comcast Xfinity"
barFolder["Children"].delete_at(i)
end
i -= 1
end
puts "Adding Folder..."
comcastBookmarksArray = []
bookmarksArray.each { |bookmark|
uri = {
"title"=>bookmark["title"]
}
bm = {
"URIDictionary" => uri,
"URLString" => bookmark["url"],
"WebBookmarkType" => "WebBookmarkTypeLeaf"
}
comcastBookmarksArray.push(bm)
}
comcastFolder = {
"Title" => "Comcast Xfinity",
"WebBookmarkType" => "WebBookmarkTypeList",
"Children" => comcastBookmarksArray
}
barFolder["Children"].push(comcastFolder)
bm_file = File.new(SAFARI_BOOKMARKS_LOCATION, "w")
bm_file.write(Plist::Emit.dump(parsedBm))
bm_file.close
end
if (system 'plutil -convert binary1 '+SAFARI_BOOKMARKS_LOCATION)
puts "successfully saved changes to Safari bookmarks"
else
puts "error saving changes to safari bookmarks!"
end
else
puts "Failed to convert Bookmarks.plist with status: "+$?.to_s
end
else
puts "could not find Safari bookmarks plist file at "+SAFARI_BOOKMARKS_LOCATION
end
##
## Homepage
##
if (File.exist?(SAFARI_PREFERENCES_LOCATION))
if (system 'plutil -convert xml1 '+SAFARI_PREFERENCES_LOCATION)
parsedPrefs = Plist::parse_xml(SAFARI_PREFERENCES_LOCATION)
puts "homepage currently set to - "+parsedPrefs["HomePage"].to_s
puts "\treplacing with Comcast homepage"
parsedPrefs["HomePage"] = homepage
pref_file = File.new(SAFARI_PREFERENCES_LOCATION,"w")
pref_file.write(Plist::Emit.dump(parsedPrefs))
pref_file.close
if (system 'plutil -convert binary1 '+SAFARI_PREFERENCES_LOCATION)
puts "successfully saved Safari preferences plist file"
else
puts "error saving changes to safari preferences"
end
else
puts "could not convert Safari preferences to xml"
end
else
puts "could not find Safari preferences file at "+SAFARI_PREFERENCES_LOCATION
end
##
## Search Provider - doesn't work :-(
##
# if (File.exist?(SAFARI_CONFIGURATION_LOCATION))
# parsedConfigs = Plist::parse_xml(SAFARI_CONFIGURATION_LOCATION)
# alreadyHasComcast = false
# puts "supports the following search providers:"
# parsedConfigs["SearchProviders"]["SearchProviderList"].each { |provider|
# puts provider["ShortName"]
# if (provider["ScriptingName"] == "Comcast")
# alreadyHasComcast = true
# end
# }
# if (!alreadyHasComcast)
# comcastNode = {
# "HomePageURLs" => [searchProviderHomepage],
# "HostSuffixes" => [".comcast.net"],
# "PathPrefixes" => ["/search"],
# "ScriptingName" => "Comcast",
# "ShortName" => "Comcast",
# "SearchUrlTemplate" => searchProviderUrl+"{searchTerms}"
# }
# parsedConfigs["SearchProviders"]["SearchProviderList"].push(comcastNode)
# configFile = File.new(SAFARI_CONFIGURATION_LOCATION,"w")
# configFile.write(Plist::Emit.dump(parsedConfigs))
# configFile.close
# end
# else
# puts "could not find Safari configuration file at "+SAFARI_CONFIGURATION_LOCATION
# end
end
##############
# Firefox
##############
FIREFOX_PROFILES_LOCATION = "Library/Application Support/Firefox/Profiles/"
FIREFOX_SEARCH_PLUGIN_LOCATION = "/Applications/Firefox.app/Contents/MacOS/searchplugins/"
## add all our settings to this profile
def add_settings_to_ff_profile(profile_name, bookmarksArray, homepage, abs_path_to_utils, supportSearch)
puts File.expand_path($0)
Dir.chdir() do
puts File.expand_path($0)
# this just tests to make sure we have all the bookmarks stuff in place for this profile
# (i.e. making sure we've used firefox under this profile)
db_location = FIREFOX_PROFILES_LOCATION+"/"+profile_name+"/places.sqlite"
sqlite3_location = abs_path_to_utils+"/sqlite3"
roots = `'#{sqlite3_location}' '#{db_location}' 'SELECT * FROM moz_bookmarks_roots'`
if ($?.to_i == 0)
puts roots
toolbar_folder_id = `'#{sqlite3_location}' '#{db_location}' 'SELECT folder_id FROM "moz_bookmarks_roots" WHERE root_name="toolbar"'`
puts "toolbar folder id = "+toolbar_folder_id
# TODO: check for the Comcast Xfinity folder
comcast_folder_id = `'#{sqlite3_location}' '#{db_location}' 'SELECT id FROM "moz_bookmarks" WHERE title="Comcast Xfinity"'`
if (comcast_folder_id != nil && comcast_folder_id!="")
puts "Xfinity bookmark folder exists"
else
# make the bookmark folder
puts `'#{sqlite3_location}' '#{db_location}' 'INSERT INTO moz_bookmarks (type, parent, title) VALUES(2,#{toolbar_folder_id},"Comcast Xfinity")'`
comcast_folder_id = `'#{sqlite3_location}' '#{db_location}' 'SELECT id FROM "moz_bookmarks" WHERE title="Comcast Xfinity"'`
puts "created Xfinity folder, id="+comcast_folder_id
# insert each bookmark into the moz_places table, get its id, add it as a bookmark
bookmarksArray.each { |bookmark|
puts "\n___________\nbookmark "+bookmark["title"]
puts `'#{sqlite3_location}' '#{db_location}' 'INSERT INTO moz_places (url, title, hidden, typed) VALUES("#{bookmark["url"]}","#{bookmark["title"]}",0,0)'`
place_id = `'#{sqlite3_location}' '#{db_location}' 'SELECT id FROM moz_places WHERE url="#{bookmark["url"]}"'`
puts "id in places db="+place_id
puts `'#{sqlite3_location}' '#{db_location}' 'INSERT INTO moz_bookmarks (type, fk, parent, position, title) VALUES(1,#{place_id},#{comcast_folder_id},0,"#{bookmark["title"]}")'`
}
end
else
puts "Error opening places database!"
# return here because we won't be able to install the extension either
return nil
end
# now add a homepage preference in user.js
#preflocation = FIREFOX_PROFILES_LOCATION+"/"+profile_name+"/user.js"
#prefs = File.new(preflocation, "a")
#prefs.write("\nuser_pref(\"browser.startup.homepage\", \"#{homepage}\");")
#if supportSearch
# prefs.write("\nuser_pref(\"browser.search.selectedEngine\", \"Xfinity\");\nuser_pref(\"browser.search.suggest.enabled\", false);")
#end
#prefs.close
# if requested, delete the search database (and its backup file), which will force FF to recreate when it starts up
#if supportSearch
# puts "removing search database so that FF will have to rebuild"
# puts "rm -rf #{FIREFOX_PROFILES_LOCATION}/#{profile_name}/search.sqlite"
#`rm -rf '#{FIREFOX_PROFILES_LOCATION}/#{profile_name}/search.sqlite'`
#`rm -rf '#{FIREFOX_PROFILES_LOCATION}/#{profile_name}/search.json'`
#end
end
end
puts "--------\nBegin Firefox Operations"
couldInstallSearch = false
# Copy the search plugin xml file into the search plugins folder if we can find it
if (File.exists?(FIREFOX_SEARCH_PLUGIN_LOCATION))
`cp '#{abs_path_to_utils}/firefox_search_plugin.xml' '#{FIREFOX_SEARCH_PLUGIN_LOCATION}/comcast.xml'`
couldInstallSearch = true
else
couldInstallSearch = false
puts 'cannot find firefox application folder. perhaps the user has installed it in a non-standard location. unable to install search plugins'
end
Dir.chdir() do
ff_profile_list = `ls '#{FIREFOX_PROFILES_LOCATION}'`.split("\n")
ff_profile_list.each { |profile_folder|
Dir.chdir() do
## This check is necessary because Firefox seems to throw random non-folders in the
## profile directory (when profiles have spaces in the names)
puts "couldInstallSearch="+couldInstallSearch.to_s
if (File.directory?(FIREFOX_PROFILES_LOCATION+profile_folder))
puts "\n--------\nprofile folder: "+profile_folder+"\n--------"
add_settings_to_ff_profile(profile_folder, bookmarksArray,homepage,abs_path_to_utils,couldInstallSearch)
else
puts 'seems this profile is not a directory '+profile_folder
end
end
}
end
print "\n----------------------------\n"
print "script add_bookmarks completed successfully\n\n\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment