{"id":3172,"date":"2025-05-25T18:23:08","date_gmt":"2025-05-25T16:23:08","guid":{"rendered":"https:\/\/digitalia.culturanuova.net\/blog\/?p=3172"},"modified":"2025-05-25T18:23:08","modified_gmt":"2025-05-25T16:23:08","slug":"esport-and-show-ff-bookmarks-in-a-webpage","status":"publish","type":"post","link":"https:\/\/digitalia.culturanuova.net\/blog\/?p=3172","title":{"rendered":"esport and show FF bookmarks in a webpage"},"content":{"rendered":"\n<p>With the help of IA I managed to <strong>get Firefox bookmarks<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport json\nimport sqlite3\nimport shutil\nimport tempfile\n\nprofile_name = \"your-profile\"  # &lt;-- cambia con il tuo\nprofile_path = os.path.expanduser(f\"~\/.mozilla\/firefox\/{profile_name}\")\ndb_path = os.path.join(profile_path, \"places.sqlite\")\n\nif not os.path.isfile(db_path):\n    print(f\"Il file places.sqlite non esiste: {db_path}\")\n    exit(1)\n\n# Copia temporanea per evitare blocchi\ntmp_dir = tempfile.gettempdir()\ntemp_db_path = os.path.join(tmp_dir, \"places_copy.sqlite\")\nshutil.copy2(db_path, temp_db_path)\n\nconn = sqlite3.connect(temp_db_path)\nconn.row_factory = sqlite3.Row\ncursor = conn.cursor()\n\n# Preleva tutte le informazioni rilevanti\nquery = \"\"\"\nSELECT\n    b.id,\n    b.title,\n    b.parent,\n    b.type,\n    b.fk,\n    b.dateAdded,\n    p.url,\n    ia.content AS description\nFROM moz_bookmarks b\nLEFT JOIN moz_places p ON b.fk = p.id\nLEFT JOIN moz_items_annos ia ON b.id = ia.item_id\nLEFT JOIN moz_anno_attributes a_attr ON ia.anno_attribute_id = a_attr.id\nWHERE (b.type = 1 OR b.type = 2)\n  AND (a_attr.name IS NULL OR a_attr.name = 'bookmarkProperties\/description')\nORDER BY b.parent, b.position\n\"\"\"\n\ncursor.execute(query)\nrows = cursor.fetchall()\n\n# Costruisci dizionario gerarchico\nitems = {row&#91;\"id\"]: {\n    \"id\": row&#91;\"id\"],\n    \"title\": row&#91;\"title\"] if row&#91;\"title\"] else \"(senza titolo)\",\n    \"type\": \"folder\" if row&#91;\"type\"] == 2 else \"bookmark\",\n    \"url\": row&#91;\"url\"] if row&#91;\"type\"] == 1 else None,\n    \"description\": row&#91;\"description\"],\n    \"children\": &#91;]\n} for row in rows}\n\n# Organizza gerarchia\nroot = &#91;]\nfor row in rows:\n    item = items&#91;row&#91;\"id\"]]\n    parent_id = row&#91;\"parent\"]\n    if parent_id in items:\n        items&#91;parent_id]&#91;\"children\"].append(item)\n    else:\n        root.append(item)\n\n# Salva in JSON\nwith open(\"bookmarks_full.json\", \"w\", encoding=\"utf-8\") as f:\n    json.dump(root, f, ensure_ascii=False, indent=2)\n\nprint(f\"Esportazione completata: {len(root)} cartelle o elementi di primo livello.\")\nconn.close()\nos.remove(temp_db_path)<\/code><\/pre>\n\n\n\n<p>also selecting a specific bookmark folder<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport sqlite3\nimport shutil\nimport tempfile\nimport sys\n\nprofile_name = \"your-FF-profile\"\nfolder_name_to_export = \"&#91;the folder name]\"  # Nome della cartella da esportare\noutput_path = \"bookmarks-FF-&#91;a name].php\"\n\n# Percorso del profilo\nprofile_path = os.path.expanduser(f\"~\/.mozilla\/firefox\/{profile_name}\")\ndb_path = os.path.join(profile_path, \"places.sqlite\")\n\nif not os.path.isfile(db_path):\n    print(f\"Il file places.sqlite non esiste: {db_path}\")\n    sys.exit(1)\n\n# Copia temporanea del DB\ntmp_dir = tempfile.gettempdir()\ntemp_db_path = os.path.join(tmp_dir, \"places_copy.sqlite\")\nshutil.copy2(db_path, temp_db_path)\n\nconn = sqlite3.connect(temp_db_path)\nconn.row_factory = sqlite3.Row\ncursor = conn.cursor()\n\n# 1. Query per cartelle e segnalibri (senza tag)\nquery = \"\"\"\nSELECT\n  b.id,\n  b.title,\n  b.parent,\n  b.type,\n  b.fk,\n  p.url\nFROM moz_bookmarks b\nLEFT JOIN moz_places p ON b.fk = p.id\nWHERE b.type IN (1, 2)\nORDER BY b.parent, b.position\n\"\"\"\n\ncursor.execute(query)\nrows = cursor.fetchall()\n\n# Costruzione struttura\nitems = {row&#91;\"id\"]: {\n    \"id\": row&#91;\"id\"],\n    \"title\": row&#91;\"title\"] or \"(senza titolo)\",\n    \"type\": \"folder\" if row&#91;\"type\"] == 2 else \"bookmark\",\n    \"url\": row&#91;\"url\"] if row&#91;\"type\"] == 1 else None,\n    \"description\": None,\n    \"children\": &#91;]\n} for row in rows}\n\n# Costruzione gerarchia\nfor row in rows:\n    item = items&#91;row&#91;\"id\"]]\n    parent_id = row&#91;\"parent\"]\n    if parent_id in items:\n        items&#91;parent_id]&#91;\"children\"].append(item)\n\n# 2. Query per associare tag reali ai segnalibri\ntag_query = \"\"\"\nSELECT\n  b.id AS bookmark_id,\n  GROUP_CONCAT(tg.title, ', ') AS tags\nFROM moz_bookmarks b\nLEFT JOIN moz_bookmarks bt ON bt.fk = b.fk\nLEFT JOIN moz_bookmarks tg ON tg.id = bt.parent AND tg.parent = -3\nWHERE b.type = 1\nGROUP BY b.id\n\"\"\"\n\ncursor.execute(tag_query)\ntag_rows = cursor.fetchall()\n\n# Assegna i tag ai segnalibri nella struttura\nfor row in tag_rows:\n    bookmark_id = row&#91;\"bookmark_id\"]\n    tags = row&#91;\"tags\"]\n    if bookmark_id in items:\n        items&#91;bookmark_id]&#91;\"description\"] = tags if tags else \"(senza tag)\"\n\n# Cerca la cartella da esportare\nmatching_folders = &#91;item for item in items.values()\n                    if item&#91;\"type\"] == \"folder\" and item&#91;\"title\"] == folder_name_to_export]\n\nif not matching_folders:\n    print(f\"Nessuna cartella trovata con nome '{folder_name_to_export}'.\")\n    conn.close()\n    os.remove(temp_db_path)\n    sys.exit(1)\n\n# Funzione per scrivere array PHP\ndef to_php_array(item, indent=2):\n    space = ' ' * indent\n    lines = &#91;f\"{space}&#91;\"]\n    lines.append(f\"{space}  'title' => '{item&#91;'title'].replace('\\'', '\\\\\\'')}',\")\n    if item.get(\"url\"):\n        lines.append(f\"{space}  'url' => '{item&#91;'url'].replace('\\'', '\\\\\\'')}',\")\n    if item.get(\"description\"):\n        lines.append(f\"{space}  'description' => '{item&#91;'description'].replace('\\'', '\\\\\\'')}',\")\n    if item.get(\"children\"):\n        lines.append(f\"{space}  'children' => &#91;\")\n        for child in item&#91;\"children\"]:\n            lines.append(to_php_array(child, indent + 4) + \",\")\n        lines.append(f\"{space}  ],\")\n    lines.append(f\"{space}]\")\n    return \"\\n\".join(lines)\n\n# Scrittura file PHP\nwith open(output_path, \"w\", encoding=\"utf-8\") as f:\n    f.write(\"&lt;?php\\nreturn &#91;\\n\")\n    for folder in matching_folders:\n        f.write(to_php_array(folder, indent=2))\n        f.write(\",\\n\")\n    f.write(\"];\\n\")\n\nprint(f\"Esportazione completata in {output_path}\")\n\nconn.close()\nos.remove(temp_db_path)<\/code><\/pre>\n\n\n\n<p>and output them in a php webpage<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n$segnalibri = include 'bookmarks-FF-&#91;a name].php';\n\nfunction stampaSegnalibri($items) {\n    foreach ($items as $item) {\n        echo \"&lt;div style='margin-bottom:8px'>\";\n\n        if (isset($item&#91;'url'])) {\n            \/\/ titolo come link\n            $title_html = htmlspecialchars($item&#91;'title'], ENT_QUOTES);\n            $url_html = htmlspecialchars($item&#91;'url'], ENT_QUOTES);\n            echo \"&lt;a href=\\\"$url_html\\\" target=\\\"_blank\\\">$title_html&lt;\/a>\";\n        } else {\n            \/\/ solo titolo testo normale\n            echo \"&lt;strong>\" . htmlspecialchars($item&#91;'title'], ENT_QUOTES) . \"&lt;\/strong>\";\n        }\n\n        \/\/ descrizione (se presente)\n        if (!empty($item&#91;'description'])) {\n            $desc_html = htmlspecialchars($item&#91;'description'], ENT_QUOTES);\n            echo \"&lt;br>&lt;small style='color: #555;'>$desc_html&lt;\/small>\";\n        }\n\n        \/\/ figli (ricorsivo)\n        if (isset($item&#91;'children']) &amp;&amp; count($item&#91;'children']) > 0) {\n            echo \"&lt;div style='margin-left:20px; margin-top:4px;'>\";\n            stampaSegnalibri($item&#91;'children']);\n            echo \"&lt;\/div>\";\n        }\n\n        echo \"&lt;\/div>\";\n    }\n}\n\nstampaSegnalibri($segnalibri);\n?><\/code><\/pre>\n\n\n\n<p>The <strong>problem<\/strong> is that FF doesn&#8217;t have a description field, and I didn&#8217;t manage tgo get it from another filed, such as &#8216;tags&#8217; one.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With the help of IA I managed to get Firefox bookmarks also selecting a specific bookmark folder and output them in a php webpage The problem is that FF doesn&#8217;t have a description field, and I didn&#8217;t manage tgo get it from another filed, such as &#8216;tags&#8217; one.<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[570,885,579,751,566],"tags":[685,27],"class_list":["post-3172","post","type-post","status-publish","format-standard","hentry","category-browsers","category-code","category-database","category-php","category-webmaster","tag-bookmarks","tag-firefox"],"_links":{"self":[{"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3172"}],"version-history":[{"count":1,"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3172\/revisions"}],"predecessor-version":[{"id":3173,"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3172\/revisions\/3173"}],"wp:attachment":[{"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digitalia.culturanuova.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}