Remotely add bookmarks to Firefox 3

Sun, 27 July, 2008

As promised in an earlier related post, here's a script to allow you to add a bookmark to your Firefox 3 Toolbar from the command line.

My use case is that I'm at work, logged into home via SSH, and I encounter an article I'd like to finish when I get home. I can run this command, and then the article is waiting for me in the Toolbar when I get home and open Firefox.

Some notes.

  • A reasnably current SQLite is required
  • It's assumed that you have a bookmarks toolbar already
  • You'll need to edit the BM_DIR variable to the directory where your bookmarks are stored.
  • The script does a lot of error-checking, and it works on a copy of your bookmarks database. This means that if something goes wrong, your bookmarks won't be corrupted.

To use it:

  • Save the following as bookmark.sh
  • chmod +x bookmark.sh
  • Configure the BM_DIR value in the script
  • ./bookmark.sh CNN http://www.cnn.com
#
# This script will add a bookmark to Firefox 3.  This is 
# useful, for example when remoting to the machine with
# only ssh access.

# Two arguments are expected: The bookmark name and the full URL
# Example:
#   ./bookmark.sh GreatArticles http://mackdanz.net
#
# Some notes:
# - SQLite is required (sqlite3 at the command line)
# - This works with Firefox 3 only.  
# - This hasn't been tested much, so use reasonable inputs,
#     no unusual characters
# - The script tries to use reasonable error-checking, but
#     I'M NOT LIABLE FOR ANY DAMAGE THAT MAY OCCUR, although
#     damage could be pretty easily repaired.
#
# (c) Erik Mackdanz, free for any use
#

######### ADJUST THIS VALUE!!! ############
# Where is your bookmark file
BM_DIR=/home/erik/.mozilla/firefox/31327a70.default
###########################################

# Check for sane inputs
if( (($# != 2)) )
then
	echo "Usage: $0 name url"
	echo "Example: $0 GreatArticles http://mackdanz.net"
	exit 1
fi

BM_FILE=places.sqlite

# Check that places database exists
if [ ! -f $BM_DIR/$BM_FILE ]
then
	echo Configured places database $BM_DIR/$BM_FILE doesnt exist, quitting
	exit 1
fi


BM_WORK=$BM_DIR/$BM_FILE.working

# Copy database into working location
if ! cp $BM_DIR/$BM_FILE $BM_WORK
then
	echo failure copying db to a working location, quitting.
	exit 1
fi

# Find the id for the toolbar links
if ! TOOLBAR_ID=`sqlite3 $BM_WORK 'SELECT folder_id FROM moz_bookmarks_roots WHERE root_name="toolbar"'`
then
	echo failure querying db for bookmarks folder, quitting.
	exit 1
fi

# Extract the host name from the full URL
URL=$2
DOMAIN=`echo $URL | sed 's/.*:\/\/(.*\)($\|\/\).*//'`

# FF wants us to insert the reversed host name
for((x=${#DOMAIN}-1;x>=0;x--))
do
	REVDOMAIN=$REVDOMAIN${DOMAIN:$x:1}
done
REVDOMAIN=$REVDOMAIN.

# I don't know what frecency is
FRECENCY=141

# Insert into place table
PLACEQUERY="INSERT INTO moz_places (url,title,rev_host,visit_count,hidden,typed,favicon_id,frecency) VALUES ('$URL','$1','$REVDOMAIN',0,0,0,NULL,$FRECENCY)"
if ! sqlite3 $BM_WORK "$PLACEQUERY"
then
	echo failure inserting place into db, quitting.
	exit 1
fi

# Get the id of the record we just inserted.  Maybe there's an easier way?
if ! PLACE_ID=`sqlite3 $BM_WORK "SELECT MAX(id) FROM moz_places"`
then
	echo failure getting latest place id from db, quitting.
	exit 1
fi

# Bookmarks are ordered with the 'position' field.
# We'll place our record at the end of the list.
if ! NEXT_POS=`sqlite3 $BM_WORK "SELECT MAX(position)+1 FROM moz_bookmarks WHERE parent=$TOOLBAR_ID"`
then
	echo failure getting next position from db, quitting.
	exit 1
fi

# Get the local timestamp in the expected format
DATE_VAL=`date +%s`000000

# Insert the place into the bookmarks table
BM_QUERY="INSERT INTO moz_bookmarks (type,fk,parent,position,title,dateAdded,lastModified) VALUES (1,$PLACE_ID,$TOOLBAR_ID,$NEXT_POS,'$1',$DATE_VAL,$DATE_VAL)"
if ! sqlite3 $BM_WORK "$BM_QUERY"
then
	echo failure inserting bookmark into db, quitting.
	exit 1
fi

# We're ready to replace the production database with our working one.
# We'll leave the original version, just in case
BM_BAK=$BM_DIR/$BM_FILE.bak
if ! cp $BM_DIR/$BM_FILE $BM_BAK
then
	echo failure backing up original db, quitting.
	exit 1
fi

# Do the swap.
if ! cp $BM_WORK $BM_DIR/$BM_FILE 
then
	echo failure switching original db with new one, quitting.
	exit 1
fi

# Clean up
rm $BM_WORK
echo Left backup of database at $BM_BAK

About Me

Erik Mackdanz is a software developer in Austin, Texas, along with everybody else.

Links