dirtyfilthy
In the grim future of 2008, there is only war.

About Bookmarks

This site autosyncs with my firefox bookmarks over an XML-RPC interface with a ruby on rails backend.

Fuck PHP. The following code is for example purposes only and WILL NOT FUNCTION AS IS. You need to define your own models and migrations and views and such. You're smart, you'll figure it out.

Rather than implementing the hierarchical tree based organisation of firefox on the serverside it considers each category to be a tag, but a tree based server side solution shouldn't be hard to sort out as the tags are still pushed in correct hierarchical order from the client.

API definition

Whack this shit in /var/www/yourapp/app/apis/bookmark_api.rb

class IncomingBookmark < ActionWebService::Struct
	member :url, :string
 	member :title, :string
	member :tags, [:string]
	member :date_added, :datetime
end

class BookmarkAPI < ActionWebService::API::Base
  	api_method :submit_bookmarks, :expects => [:string,[IncomingBookmark]], :returns => [:boolean]
end


Bookmarks controller

Goes in /var/www/yourapp/app/controller/bookmarks_controller.rb

class BookmarksController < ApplicationController
	web_service_dispatching_mode :delegated
	web_service :xmlrpc, BookmarkService.new
	layout "site"
	$page_title="Bookmarks."
	before_filter :setup_bookmarks
	before_filter :get_bookmark_tags


	def setup_bookmarks
		$page_title="Bookmarks."
		$bookmark_page=true;
	end

	def get_bookmark_tags
	 	@tags=Tag.find :all, :order => "name ASC"
		@tags.delete_if do |tag| tag.bookmarks.empty? end
	end

	def list
		@message="Last twenty bookmarks"
		@bookmarks=Bookmark.find :all,:order => "added_on DESC",:limit => 20
	end

	def rss
	    @bookmarks = Bookmark.find :all,:order => "added_on DESC",:limit => 20
	    render  :layout =>  false
	end

	def about
	    @message = "About dirtyfilthy bookmarks"
	end

	def tag
		t=Tag.find_by_name(params[:name])
		unless t.nil?
			@message="Showing bookmarks with tag &quot;#{t.name}&quot;"
			@bookmarks=t.bookmarks
		else
			@message="No such tag: &quot;#{params[:name]}&quot;"
			@bookmarks=Bookmark.find :all,:order => "added_on DESC",:limit => 20
		end
		render "bookmarks/list"
	end

end

Actual bookmarks service

/var/www/yourapp/app/models/bookmark_service.rb

Change "mypassword" to your own password.

class IncomingBookmark < ActionWebService::Struct
        member :url, :string
        member :title, :string
        member :tags, [:string]
        member :date_added, :datetime
end


class BookmarkService < ActionWebService::Base
	web_service_api BookmarkAPI

  	def submit_bookmarks(password,bookmarks)

		# shitty, shitty auth mech

		mypassword="sallyslurper"
		if password!=mypassword
			return false;
		end
		
		bookmarks.each do |b|
			b.tags=b.tags-["Bookmarks Toolbar Folder"]
			next if b.tags.empty? 
			bm=Bookmark.find_or_create_by_url(b.url)
			tags=Array.new
			b.tags.each do |t|
				mt=Tag.find_or_create_by_name(t)
				tags << mt
			end
			bm.tags=tags
			bm.title=b.title
			bm.added_on=b.date_added if bm.added_on.nil?
			bm.save
		end
		return true
    
    	end

end

Clientside code

This is run on the client side from cron say once an hour. It parses your bookmark file and uploads it via xmlrpc. Set password to be the same as above

#!/usr/bin/ruby

# Modified by dirtyfilthy from original code by:

# Exports Firefox bookmarks to a readable XML for 
# use by Safari
# 30-03-06, Premshree Pillai

require "cgi"
require "pp"
require 'xmlrpc/client'

# set this to the location of your bookmarks file

ff_bookmarks_file = "/home/alhazred/.mozilla/firefox/y7litjgc.default/bookmarks.html"

# set this to the location of your xmlrpc service

bookmark_service="http://www.dirtyfilthy.net/bookmarks/xmlrpc"

# set this to your password ( really shitty auth meth :/ )

password="sallyslurper"


tag_stack=Array.new
bookmarks=Array.new
xml_data = File.open(ff_bookmarks_file).readlines
xml_data.each { |line|
	if line =~ /<H3.*?>(.*?)<\/H3>/
		tag_stack.push($1);
	end

	if line =~ /<\/DL><p>/
		tag_stack.pop
	end
	

	if line =~ /<DT><A HREF="(.*?)" ADD_DATE="(.*?)".*>(.*?)\<\/A>/
		bookmark=Hash.new
		bookmark["url"]=$1;
		bookmark["date_added"]=Time.at($2.to_i);
		bookmark["title"]=$3;
		bookmark["tags"]=tag_stack.clone
		bookmarks << bookmark
	end
}

server = XMLRPC::Client.new2(bookmark_service)
result = server.call("SubmitBookmarks", password, bookmarks)