Sunday, October 9, 2011

Unwanted Comcast features

After multiple occurrences of AT&T dropping connections over the past months, I finally decided to switch to Comcast (yes, I have heard many terrible stories about their billing department, sales fraud, etc.). Plus, I got a really good deal from my colleague ($19 per month for the first year, $35 per month for the second year for their performance package, 15MB upload and 5MB download.

Based on advice, I did not choose to rent their modem and bought my own from Amazon: Motorola SB6121 and it worked great. There is an older model SB6120 that is a bit cheaper, but my friend had problems. Please check with the technician and confirm that those models work in your area.

Today, they came in and installed it for me. The overall process worked fine except for three complaints:

1.  They kept calling for confirmation. In the past week, they called so many times for confirmation, 3 days before, yesterday, and this morning. I understand that some people might be forgetting things very quickly, but I am not that type of people. Plus, I have confirmed at the first call already and they are still calling as early as 7am in the morning! Since I did not get this morning's phone call, they left a message and said I would have to reschedule it, WTF. So, I ended up calling them again so they can send the technician in without rescheduling.

2. Some technicians are un-professional. I am quite busy with work and life, so my appointment is 8-10am, earliest I could get so I don't miss the work. For the first appointment, the technician waited outside for 1 hour before he came in (I saw his van and went out to tell him I am ready, but he kept sitting in his var for another half an hour). When he came in, I showed him where I want the setup and the pole to pull the signal from. He shrugged his shoulder and said "it will take at least 4-5 hours". I said I thought it'd be only 1-2 hours and I had no choice but to reschedule. Somehow from the look on his face, I felt that he did not want to do installation (bad mood, lazy, etc.) and I am fairly pissed. If you don't want to work, then don't come to waste your time and my time.

Today, another technician came in and he is much better. He finished the whole job in 1 hr and told me the previous technician "must be lazy".

3. The installation process forces you to install the desktop installer to activate. After the hardware is set up, I hooked up my wireless router and was directed to an activation page, which asked me to create a new Comcast user account. But the last step is to install Comcast desktop installer and there seems to be no way around according to the technician. (Update: according to my colleague, you don't need to install it, just restart the modem, shutdown router, connect router with modem, start the router. But I did not try this personally, not sure if it would work.)

The installer file is "ComcastDesktopInstaller_MMF3.pkg" in my case. I uploaded it online if you are interested. Luckily I unchecked "install browser toolbar" option during installation. People are suffering from this toolbar since it hijacks browser preferences and homepage. If you are the victim, please follow instructions on this page to get your previous setting restored.

After the network is up and running, I want to uninstall it but could not find much info. I did my best, and my conclusion is it might not do as much harm. It executed some Ruby scripts and installed some crap on the desktop, which you can delete easily.


Cleanup actions in summary:


1. Delete the two website shortcuts installed on my desktop.
2. Delete ~/.cim_install_log. 
3. I am not familiar with Ruby, but the scripts seems to just create Xfinity bookmarks for Safari, Firefox and Chrome. For details in the script, see the gist below.
4. Besides those, I did not seem to find other suspicious malware or unwanted junks.

Detailed checkups for the Comcast app:

1. Did a grep for "comcast" and found a log file in home directory: ~/.cim_install_log. It contains all the output during installation process.
2. Used AppCleaner to check installed applications, does not find any malicious app installed from Comcast installer.
3. Used pkgutil command to search for anything related to comcast in package receipt database. See pkgutil manpage for details how to use it. I could not find any new applications installed from this installer pkg.
4. Used Pacifist to check the content of the pkg file. Did not see much suspicious content except for several Ruby and shell scripts to run during installation.

Don't install Firefox Toolbar

By default, these website shortcuts are install on your desktop, remove them


Content of ComcastDesktopInstaller_MMF3.pkg


#!/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"

#!/bin/bash
# A script to add some bookmarks to any supported browsers
echo "shell script running">> ~/.cim_install_log
echo $1>> ~/.cim_install_log
echo $2>> ~/.cim_install_log
echo "run ruby script from:">> ~/.cim_install_log
echo $2/ruby/add_bookmarks.rb>> ~/.cim_install_log
cd $2/ruby
ruby $2/ruby/add_bookmarks.rb>> ~/.cim_install_log 2>&1
exit 0
require "rexml/document"
require "fileutils"
FIREFOX_PROFILES_LOCATION = "Library/Application Support/Firefox/Profiles/"
TEMP_DIRECTORY = "comcast_temp_000123"
FIREFOX_TOOLBAR_FILENAME = "XfinitydotcomToolbarMAC.xpi"
abs_path_xpi_directory = File.dirname($0)
# user may pass a commandline argument to override the default location
# of the xpi
if (ARGV[0] != nil)
abs_path_xpi_directory = ARGV[0]
end
# add all our settings to this profile
def add_settings_to_ff_profile(profile_name, abs_path_xpi_directory)
clsid = nil
Dir.chdir(abs_path_xpi_directory) do
if (File.exist?TEMP_DIRECTORY)
`rm -rf '#{TEMP_DIRECTORY}'`
end
Dir.mkdir(TEMP_DIRECTORY)
`unzip '#{FIREFOX_TOOLBAR_FILENAME}' -d '#{TEMP_DIRECTORY}'`
manifest = File.new(TEMP_DIRECTORY+"/manifest.xml")
doc = REXML::Document.new manifest
clsid = doc.get_elements("toolbar-manifest/dtx")[0].attributes["clsid"].to_s()
manifest.close
end
Dir.chdir() do
dirlocation = FIREFOX_PROFILES_LOCATION+profile_name+"/extensions/"+clsid
if (!File.exist?(dirlocation) || Dir.entries(dirlocation).length < 3)
if (File.exists?(dirlocation))
puts "exists, delete it"
Dir.delete(dirlocation)
end
FileUtils.mkdir_p(dirlocation)
puts "copy file: "+abs_path_xpi_directory+"/"+TEMP_DIRECTORY+"/."
FileUtils.cp_r(abs_path_xpi_directory+"/"+TEMP_DIRECTORY+"/.", dirlocation)
puts "toolbar installed"
else
puts "it seems the firefox toolbar is already installed"
end
end
Dir.chdir(File.dirname($0)) do
`rm -rf '#{TEMP_DIRECTORY}'`
end
end
Dir.chdir() do
puts "running script from "+File.expand_path($0)
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)
if (File.directory?(FIREFOX_PROFILES_LOCATION+profile_folder))
puts "\n--------\nprofile folder: "+profile_folder+"\n--------"
add_settings_to_ff_profile(profile_folder, abs_path_xpi_directory)
else
puts 'seems this profile is not a directory '+profile_folder
end
end
}
end

#!/bin/bash
echo "begin script install_ff_plugin">> ~/.cim_install_log
cd "/tmp/comcast_002/Firefox Plugin/">> ~/.cim_install_log
ruby install_ff_plugin.rb "/tmp/comcast_002/Firefox Plugin">> ~/.cim_install_log 2>&1


 Reference: