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 "#{t.name}"" @bookmarks=t.bookmarks else @message="No such tag: "#{params[:name]}"" @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)