Class: FirefoxBookmarkParser

Inherits:
BookmarkParser show all
Defined in:
lib/bookmarks.rb

Overview

Firefox bookmark parser (SQLite format)

Instance Attribute Summary

Attributes inherited from BookmarkParser

#allurls

Instance Method Summary collapse

Methods inherited from BookmarkParser

#initialize, #results

Constructor Details

This class inherits a constructor from BookmarkParser

Instance Method Details

#parseObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/bookmarks.rb', line 124

def parse
  begin
    require "sqlite3"
  rescue LoadError
    puts "Error: ".red + "sqlite3 gem not installed"
    puts "Run: ".grn + "gem install sqlite3"
    return
  end

  db_path = @file_path

  # Copy database to temp file if Firefox is running (to avoid lock)
  if firefox_running?
    require "tempfile"
    temp = Tempfile.new(["places", ".sqlite"])
    temp.close
    FileUtils.cp(@file_path, temp.path)
    db_path = temp.path
  end

  begin
    db = SQLite3::Database.new(db_path)
    db.results_as_hash = true

    # Recursive CTE query to build folder paths
    query = <<-SQL
      WITH RECURSIVE bookmark_tree(id, parent, title, url, path) AS (
        -- Start with bookmarks toolbar root
        SELECT b.id, b.parent, b.title, p.url,
               CAST(b.title as TEXT) as path
        FROM moz_bookmarks b
        LEFT JOIN moz_places p ON b.fk = p.id
        WHERE b.parent = (
          SELECT id FROM moz_bookmarks
          WHERE guid = 'toolbar_____'
        )

        UNION ALL

        -- Recursively get children
        SELECT b.id, b.parent, b.title, p.url,
               CAST(bt.path || '/' || b.title as TEXT) as path
        FROM moz_bookmarks b
        INNER JOIN bookmark_tree bt ON b.parent = bt.id
        LEFT JOIN moz_places p ON b.fk = p.id
      )
      SELECT id, title, path, url
      FROM bookmark_tree
      WHERE url IS NOT NULL
      ORDER BY path, title
    SQL

    db.execute(query).each do |row|
      folder_path = row["path"].to_s.split("/")[0..-2].join("/") + "/"
      folder_path = "|" + folder_path.gsub(/[:,'"]/, "-").downcase

      values = [folder_path, row["title"], row["url"], row["id"].to_s]
      if matches_search?(values)
        @allurls << Bookmark.new(
          folder_path,
          row["title"] || "",
          row["url"] || "",
          row["id"].to_s
        )
      end
    end
  rescue SQLite3::Exception => e
    puts "Error: ".red + "Could not read Firefox bookmarks database"
    puts e.message
  ensure
    db&.close
    temp&.unlink
  end
end