Wydobywanie ciekawych informacji z zakładek i historii Firefoksa 3

W przeglądarce Firefox od wersji 3 funkcjonalność zakładek i historii została zaimplementowana jako relacyjna baza danych SQLite. Wiąże się to ze znacznym zwiększeniem możliwości przeszukiwania zgromadzonych w ten sposób informacji, choć niestety z elastyczności tej nie można w pełni korzystać bezpośrednio z przeglądarki. Z Internetu korzystam w dość intensywny sposób, w przeglądarce mam ponad 2000 zakładek i codziennie zdarza się dodawać nowe. Chociaż staram się to jakoś zorganizować według folderów i etykiet, jednak do pełni szczęścia potrzebowałem 2 informacji:

  • Zobaczyć zakładki dodane w ciągu ostatnich x dni

  • Zobaczyć w jakim folderze znajduje się zakładka (prawdopodobnie moje nazewnictwo folderów nie sprawdza się rewelacyjnie ;) )

Ponieważ jest to baza danych, od razu przychodzi na myśl potencjalna możliwość zadawania zapytań w języku SQL. Poniżej opisuję narzędzia którymi można to zrobić, ich sposób użycia oraz kod przykładowych zapytań SQL.

Znaleziony i używany przeze mnie program do otwierania bazy danych SQLite to SQLite Browser. Nie wymaga on instalacji, bezpośredni link spod którego można go pobrać jest tutaj.

Dodatkowe informacje i narzędzia (które jednak nie są konieczne do wykonania tej “sztuczki”), w tym również fizyczny schemat bazy danych użytej w Firefoksie znajduje się na http://www.firefoxforensics.com/.

Pierwszą czynnością jaką należy wykonać jest skopiowanie (dla bezpieczeństwa) pliku bazy danych w inne miejsce spod, którego będzie on otwierany w SQLite Browser. Może być konieczne włączenie widoku ukrytych plików w opcjach folderów Windows. Plik nazywa się “places.sqlite” i znajduje się

  • W systemie Windows XP:

    C:\Documents and Settings\<nazwa użytkownika>\Application Data\Mozilla\Firefox\Profiles\<ciąg znaków i cyfr>\
    
  • W systemie Windows Vista:

    C:\Users\<nazwa użytkownika>\AppData\Roaming\Mozilla\Firefox\Profiles\<ciąg znaków i cyfr>\
    

Po uruchomieniu SQLite Browser otwieramy skopiowany plik “places.sqlite” i przechodzimy do zakładki Execute SQL. W pierwszym okienku wklejamy kod zapytania SQL a w kolejnym okienku baza danych podaje wynik. Poniżej kilka przykładowych zapytań.

1. Folder zawierający daną zakładkę. Nazwę szukanej zakładki wpisujemy pomiędzy znaki %, tutaj jest to “codeflux”.

SELECT title FROM moz_bookmarks WHERE id = (SELECT moz_bookmarks.parent        
from         
moz_bookmarks, moz_places         
where moz_places.url like '%codeflux%'         
AND         
moz_bookmarks.fk = moz_places.id       
AND        
moz_places.visit_count > 0)

2. Zakładki dodane w ciągu ostatnich x dni. Tutaj sprawa może być trochę bardziej skomplikowana, jeśli wśród naszych zakładek znajdują się kanały RSS. Z punktu widzenia bazy danych są one nieodróżnialne od zwykłych zakładek, a ponieważ kanały RSS aktualizują się bardzo często może się okazać że większość wyniku tego zapytania będą stanowić jakieś pozycje np. aktualności z kanału RSS. Niemniej jednak ten sposób korzystania z RSS jest mało efektywny (polecam Google Reader) i raczej rzadko używany, więc nie powinno to stanowić problemu. W poniższym zapytaniu liczba dni to 4.

select datetime( (dateAdded/1000000), 'unixepoch' ) , moz_bookmarks.title, moz_places.url, moz_bookmarks.parent        
from         
moz_bookmarks, moz_places         
where ( strftime('%s', 'now') - strftime('%s', datetime( (dateAdded/1000000),'unixepoch')) < 4*86400) AND         
moz_bookmarks.fk = moz_places.id       
AND        
moz_places.visit_count > 0

3. 20 najczęściej odwiedzanych stron.

SELECT *        
FROM moz_places         
ORDER by visit_count DESC         
LIMIT 20

4. Liczba unikatowych stron internetowych. Z moich obserwacji wynika, że chodzi o liczbę różnych stron w tym sensie, że wszystkie odwiedzane podstrony liczą się raz - tak jak strona główna. Przykładowo - wejście na stronę Onet.pl i przeglądanie działów prognoz pogody, wiadomości, sportu również będzie się liczyło raz - ponieważ wszystko to jest “w obrębie” strony Onet.pl. Liczba jest tylko przybliżona, bo mogą wliczyć się pobierane pliki oraz niektóre długie i nietypowe adresy mogą policzyć się kilka razy chociaż są podstronami. Z resztą widać to na liście tych stron - punkt 4.

SELECT COUNT(*) FROM ( SELECT count(moz_places.rev_host), url        
FROM moz_places, moz_historyvisits         
WHERE moz_places.id = moz_historyvisits.place_id         
GROUP BY moz_places.rev_host         
ORDER BY url ASC )

5. Jak wyżej, tylko lista tych stron

SELECT count(moz_places.rev_host), url        
FROM moz_places, moz_historyvisits         
WHERE moz_places.id = moz_historyvisits.place_id         
GROUP BY moz_places.rev_host         
ORDER BY url ASC

6. Lista wszystkich adresów internetowych przechowywanych w historii

SELECT url, datetime( (visit_date/1000000), 'unixepoch' )        
FROM moz_places, moz_historyvisits         
WHERE [moz_places.id](http://moz_places.id) = moz_historyvisits.place_id        
ORDER by visit_date DESC

Kilka nieco innych zapytań znajduje się na wspominanej wyżej stronie Firefoxforensics. Zachęcam do różnych twórczych eksperymentów z formułowaniem zapytań - jeśli uda się napisać coś ciekawego zapraszam do komentarzy. Polecam raczej wzorowanie się na istniejących zapytaniach niż próbę zrozumienia struktury bazy danych - widać, że jest ona zdenormalizowana (zapewne aby zapewnić szybkość działania nowego paska adresu) i przez to dość niejasna. Co prawda pewnie na deweloperskich stronach Mozilli znajduje się dokumentacja, ale osobiście nie miałem ochoty w to wnikać. Bardzo dobrym (na początek) źródłem wiedzy o języku SQL jest dział na stronie W3Schools.