logo

badwolf

minimalist and privacy-oriented web browser based on WebKitGTK git clone https://hacktivis.me/git/badwolf.git
commit: a7ba36264f3a62013d393075bd992ac252d3e51a
parent abb47b4c0faf2eadcdce62c285fea8af7edd8894
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun,  3 Nov 2019 21:34:46 +0100

Add support for XBEL Bookmarks

Diffstat:

MKnowledgeBase.md17+++++++++++++++++
MMakefile2+-
MREADME.md1+
Mbadwolf.110++++++++--
Mbadwolf.c1+
Mbookmarks.c99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
6 files changed, 100 insertions(+), 30 deletions(-)

diff --git a/KnowledgeBase.md b/KnowledgeBase.md @@ -2,3 +2,20 @@ - WebKit2 Extensions Tutorial: https://blogs.igalia.com/carlosgc/2013/09/10/webkit2gtk-web-process-extensions/ - https://trac.torproject.org/projects/tor/wiki/doc/ImportantGoogleChromeBugs / https://trac.torproject.org/projects/tor/ticket/1925 - https://webkit.org/blog/3476/content-blockers-first-look/ + +# Bookmark formats +The different plain-text formats used by web browsers found in the wild, done +in Augmented Backus–Naur Form (ABNF). + +url = *CHAR +title = *CHAR + +## uzbl +bookmark = URL TAB title [TAB tags] +tags = *(*CHAR SP) + +Documenter comment: How does it manages when the separator (TAB here) is +present in the title? + +## qutebrowser +bookmark = URL SP title diff --git a/Makefile b/Makefile @@ -24,7 +24,7 @@ INKSCAPE ?= inkscape # for i in 24 32 48 64 128 256; do echo icons/hicolor/${i}x${i}/apps/badwolf.png; done | tr '\n' ' ' ICON_SIZES = icons/hicolor/24x24/apps/badwolf.png icons/hicolor/32x32/apps/badwolf.png icons/hicolor/48x48/apps/badwolf.png icons/hicolor/64x64/apps/badwolf.png icons/hicolor/128x128/apps/badwolf.png icons/hicolor/256x256/apps/badwolf.png -DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4 +DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4 libxml-2.0 SRCS = bookmarks.c uri.c uri_test.c keybindings.c downloads.c badwolf.c OBJS = bookmarks.o uri.o keybindings.o downloads.o badwolf.o OBJS_test = uri_test.o diff --git a/README.md b/README.md @@ -55,6 +55,7 @@ Dependencies are: - C11 Compiler (such as clang or gcc) - [WebKitGTK](https://webkitgtk.org/), only the latest stable is supported +- [libxml-2.0](http://www.xmlsoft.org/), no known version limitation - POSIX make with extension for shell in variables (works with GNU, {Net,Free,Open}BSD) - A pkg-config implementation (pkgconf is recommended) - (optionnal) gettext implementation (such as GNU Gettext) diff --git a/badwolf.1 b/badwolf.1 @@ -75,8 +75,14 @@ A more generic variable name is also intended to be used in the future. .El .Sh FILES .Bl -tag -width Ds -compact -.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/URLs.txt -File containing a URL on each line. [UNSTABLE] +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/bookmarks.xbel +XBEL (XML Bookmark Exchange Language) file, known to be currently supported by: +.Xr elinks 1 , +.Xr konqueror 1 , +.Xr kbookmarkeditor 1 . Doing a symbolic link from their path works fine. +.Pp +For more information about this format see: +.Lk http://pyxml.sourceforge.net/topics/xbel/ .It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extensions/ Directory containing the .Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions diff --git a/badwolf.c b/badwolf.c @@ -7,6 +7,7 @@ #include "config.h" #include "downloads.h" #include "bookmarks.h" +#include "config.h" #include "keybindings.h" #include "uri.h" diff --git a/bookmarks.c b/bookmarks.c @@ -1,45 +1,90 @@ -#include "badwolf.h" #include "bookmarks.h" -#include <gtk/gtk.h> +#include "badwolf.h" + #include <glib/gprintf.h> /* g_fprintf() */ +#include <gtk/gtk.h> +#include <libxml/xpath.h> void -location_completion_init() +location_completion_setup(GtkListStore *list_store) { - GtkTreeIter iter; - GtkListStore *list_store; - GIOChannel *file_channel; - GError *file_err = NULL; - gchar *file_line; + gtk_entry_completion_set_model(location_completion, GTK_TREE_MODEL(list_store)); + gtk_entry_completion_set_text_column(location_completion, 0); +} - location_completion = gtk_entry_completion_new(); +void +location_completion_cleanup(xmlXPathObjectPtr xpathObj, xmlXPathContextPtr xpathCtx, xmlDocPtr doc) +{ + if(xpathObj != NULL) xmlXPathFreeObject(xpathObj); + if(xpathCtx != NULL) xmlXPathFreeContext(xpathCtx); + if(doc != NULL) xmlFreeDoc(doc); +} - list_store = gtk_list_store_new(1, G_TYPE_STRING); +GtkTreeIter +load_xpath_results(GtkListStore *list_store, xmlNodeSetPtr nodes) +{ + GtkTreeIter iter; + int size; - gchar *filename = g_build_filename(g_get_user_data_dir(), "badwolf", "URLs.txt", NULL); - g_fprintf(stderr, "URL Completion: loading at %s\n", filename); - file_channel = g_io_channel_new_file(filename, "r", &file_err); + size = (nodes) ? nodes->nodeNr : 0; - if(file_channel != NULL) - { - while(G_IO_STATUS_NORMAL == - g_io_channel_read_line(file_channel, &file_line, NULL, NULL, &file_err)) + g_fprintf(stderr, "Bookmarks: Found %d bookmarks.\n", size); + for(int i = 0; i < size; i++) + if(nodes->nodeTab[i]) { gtk_list_store_append(list_store, &iter); - gtk_list_store_set(list_store, &iter, 0, g_strchomp(file_line), -1); + gtk_list_store_set( + list_store, &iter, 0, (char *)xmlXPathCastNodeToString(nodes->nodeTab[i]), -1); } - g_free(file_line); - g_io_channel_unref(file_channel); - //g_io_channel_shutdown(file_channel, FALSE, &file_err); - g_fprintf(stderr, "URL Completion: Done.\n"); - } - else - g_fprintf(stderr, "URL Completion: Failed to load file.\n"); + return iter; +} + +void +location_completion_init() +{ + const xmlChar *xpathExpr = "//bookmark/@href"; + char *filename = g_build_filename(g_get_user_data_dir(), "badwolf", "bookmarks.xbel", NULL); + xmlDocPtr doc = NULL; + xmlXPathContextPtr xpathCtx = NULL; + xmlXPathObjectPtr xpathObj = NULL; + GtkTreeIter iter; + GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING); + + location_completion = gtk_entry_completion_new(); gtk_list_store_append(list_store, &iter); gtk_list_store_set(list_store, &iter, 0, homepage, -1); - gtk_entry_completion_set_model(location_completion, GTK_TREE_MODEL(list_store)); - gtk_entry_completion_set_text_column(location_completion, 0); + g_fprintf(stderr, "Bookmarks: loading at %s\n", filename); + doc = xmlParseFile(filename); + if(doc == NULL) + { + g_fprintf(stderr, "Bookmarks: unable to parse file \"%s\"\n", filename); + location_completion_cleanup(xpathObj, xpathCtx, doc); + return; + } + + xpathCtx = xmlXPathNewContext(doc); + if(xpathCtx == NULL) + { + g_fprintf(stderr, "Bookmarks: unable to create new XPath context\n"); + location_completion_cleanup(xpathObj, xpathCtx, doc); + return; + } + + xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); + if(xpathObj == NULL) + { + g_fprintf(stderr, "Bookmarks: unable to evaluate xpath expression \"%s\"\n", xpathExpr); + location_completion_cleanup(xpathObj, xpathCtx, doc); + return; + } + + iter = load_xpath_results(list_store, xpathObj->nodesetval); + + location_completion_cleanup(xpathObj, xpathCtx, doc); + location_completion_setup(list_store); + + g_fprintf(stderr, "Bookmarks: Done.\n"); }