[wiki] [sites] surf fifo patch || avalonwilliams

From: <git_AT_suckless.org>
Date: Fri, 11 Mar 2022 00:59:40 +0100

commit 48263a781ea60559d2fc559e831e69c13f78139a
Author: avalonwilliams <avalonwilliams_AT_protonmail.com>
Date: Thu Mar 10 18:59:04 2022 -0500

    surf fifo patch

diff --git a/surf.suckless.org/patches/fifo/bw-dmenu-fill b/surf.suckless.org/patches/fifo/bw-dmenu-fill
new file mode 100755
index 00000000..2fb9da86
--- /dev/null
+++ b/surf.suckless.org/patches/fifo/bw-dmenu-fill
_AT_@ -0,0 +1,85 @@
+#!/bin/sh
+# bitwarden dmenu script - based off of the autofill userscript from qutebrowser
+# requires the fifo patch
+# $1: winid
+#
+# add something like this to your config.h:
+# #define BITWARDEN_DMENU { .v = (char *[]){ "/bin/sh", "-c", "bw-dmenu-fill" } }
+#
+# and this to your keybindings:
+# { MODKEY, GDK_KEY_z, spawn, BITWARDEN_DMENU },
+
+fifo=~/.surf/fifo/"$1"
+url=$(xprop -id "$1" _SURF_URI | awk '{ print $3 }' | sed 's/"//g')
+
+username=""
+password=""
+
+output=$(bitwarden-dmenu \
+ --bw-list-args="--url=$url" \
+ --dmenu-args="-l 5 -w $1" \
+ --dmenu-pswd-args="-w $1" \
+ --stdout)
+
+if [ ! -z "$output" ]; then
+ username=$(echo "$output" | awk 'FNR == 1 {print}')
+ password=$(echo "$output" | awk 'FNR == 2 {print}')
+else
+ exit
+fi
+
+javascript_escape() {
+ sed "s,[\\'\"],\\&,g" <<< "$1"
+}
+
+js() {
+cat <<EOF
+ function isVisible(elem) {
+ var style = elem.ownerDocument.defaultView.getComputedStyle(elem, null);
+ if (style.getPropertyValue("visibility") !== "visible" ||
+ style.getPropertyValue("display") === "none" ||
+ style.getPropertyValue("opacity") === "0") {
+ return false;
+ }
+ return elem.offsetWidth > 0 && elem.offsetHeight > 0;
+ };
+ function hasPasswordField(form) {
+ var inputs = form.getElementsByTagName("input");
+ for (var j = 0; j < inputs.length; j++) {
+ var input = inputs[j];
+ if (input.type == "password") {
+ return true;
+ }
+ }
+ return false;
+ };
+ function loadData2Form (form) {
+ var inputs = form.getElementsByTagName("input");
+ for (var j = 0; j < inputs.length; j++) {
+ var input = inputs[j];
+ if (isVisible(input) && (input.type == "text" || input.type == "email")) {
+ input.focus();
+ input.value = "$(javascript_escape "${username}")";
+ input.blur();
+ }
+ if (input.type == "password") {
+ input.focus();
+ input.value = "$(javascript_escape "${password}")";
+ input.blur();
+ }
+ }
+ };
+ var forms = document.getElementsByTagName("form");
+ for (i = 0; i < forms.length; i++) {
+ if (hasPasswordField(forms[i])) {
+ loadData2Form(forms[i]);
+ }
+ }
+EOF
+}
+
+printjs() {
+ js | sed 's,//.*$,,' | tr '
' ' '
+}
+
+echo "inject $(printjs)" >> "$fifo"
diff --git a/surf.suckless.org/patches/fifo/index.md b/surf.suckless.org/patches/fifo/index.md
new file mode 100644
index 00000000..d0317229
--- /dev/null
+++ b/surf.suckless.org/patches/fifo/index.md
_AT_@ -0,0 +1,29 @@
+FIFO
+====
+
+Description
+-----------
+
+This patch adds a small command language that allows the browser to
+be controlled through a FIFO pipe. The format of the language is just:
+ [command] [argument]
+
+The fifo pipe of the window is stored in the `~/.surf/fifo/` directory
+by default, with the name of the file being the window id.
+
+Most of the commands are the same as their respective functions, (loaduri,
+scrollv, scrollh, etc.), though there are a couple that are different. In
+addition, a new function (injectjs) was added to allow injection of javascript
+through the pipe, though it can also be bound to a key.
+
+Download
+--------
+* [surf-fifo-20220310-c5c1646.diff](surf-fifo-20220310-c5c1646.diff) (8.2K)
+
+Scripts
+-------
+* Bitwarden autofiller: (bw-dmenu-fill)[bw-dmenu-fill] (2.4K)
+
+Authors
+-------
+* Avalon Williams <avalonwilliams_AT_protonmail.com>
diff --git a/surf.suckless.org/patches/fifo/surf-fifo-20220310-c5c1646.diff b/surf.suckless.org/patches/fifo/surf-fifo-20220310-c5c1646.diff
new file mode 100644
index 00000000..e4e97bdb
--- /dev/null
+++ b/surf.suckless.org/patches/fifo/surf-fifo-20220310-c5c1646.diff
_AT_@ -0,0 +1,309 @@
+From c5c1646470c4a278a9e44dc3934b4e0346518d40 Mon Sep 17 00:00:00 2001
+From: avalonwilliams <avalonwilliams_AT_protonmail.com>
+Date: Wed, 9 Mar 2022 23:53:08 -0500
+Subject: [PATCH] fifo patch
+
+Adds a small command language for remote control of surf through
+a fifo pipe, allowing for more complex scripts and features to be
+added through shell scripts. Also adds a javascript injection function
+that you can bind keys to.
+---
+ config.def.h | 1 +
+ surf.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 211 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index 1355ba3..dcc8d64 100644
+--- a/config.def.h
++++ b/config.def.h
+_AT_@ -6,6 +6,7 @@ static char *styledir = "~/.surf/styles/";
+ static char *certdir = "~/.surf/certificates/";
+ static char *cachedir = "~/.surf/cache/";
+ static char *cookiefile = "~/.surf/cookies.txt";
++static char *fifodir = "~/.surf/fifo/";
+
+ /* Webkit default features */
+ /* Highest priority value will be used.
+diff --git a/surf.c b/surf.c
+index 03d8242..327698e 100644
+--- a/surf.c
++++ b/surf.c
+_AT_@ -17,6 +17,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
+
+ #include <gdk/gdk.h>
+ #include <gdk/gdkkeysyms.h>
+_AT_@ -141,6 +143,24 @@ typedef struct {
+ regex_t re;
+ } SiteSpecific;
+
++typedef enum {
++ ARGTYPE_INT,
++ ARGTYPE_FLT,
++ ARGTYPE_STR,
++ ARGTYPE_NIL,
++} ArgType;
++
++typedef struct {
++ char *cmd;
++ void (*func)(Client *c, const Arg *a);
++ ArgType t;
++} Cmd;
++
++typedef struct {
++ char *p;
++ ParamName pv;
++} ParamMap;
++
+ /* Surf */
+ static void die(const char *errstr, ...);
+ static void usage(void);
+_AT_@ -239,6 +259,13 @@ static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h);
+ static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h);
+ static void clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h);
+
++static gboolean init_fifo(Client *c);
++static gboolean start_fifo(Client *c, char *path);
++static void fifo_read_cb(GObject *f, GAsyncResult *r, gpointer d);
++static void dispatchcmd(Client *c, char *cmd, char *a);
++static void injectjs(Client *c, const Arg *a);
++static void togglewrapper(Client *c, const Arg *a);
++
+ static char winid[64];
+ static char togglestats[11];
+ static char pagestats[2];
+_AT_@ -255,6 +282,7 @@ static Parameter *curconfig;
+ static int modparams[ParameterLast];
+ static int spair[2];
+ char *argv0;
++static GFile *fifof;
+
+ static ParamName loadtransient[] = {
+ Certificate,
+_AT_@ -298,6 +326,45 @@ static ParamName loadfinished[] = {
+ ParameterLast
+ };
+
++static ParamMap paramnames[] = {
++ { "autoplay", MediaManualPlay },
++ { "caret", CaretBrowsing },
++ { "frameflat", FrameFlattening },
++ { "geolocation", Geolocation },
++ { "hidebg", HideBackground },
++ { "images", LoadImages },
++ { "indicators", ShowIndicators },
++ { "java", Java },
++ { "js", JavaScript },
++ { "kiosk", KioskMode },
++ { "microphone", AccessMicrophone },
++ { "scrollbars", ScrollBars },
++ { "smoothscroll", SmoothScrolling },
++ { "spellcheck", SpellChecking },
++ { "stricttls", StrictTLS },
++ { "style", Style },
++ { "webcam", AccessWebcam },
++ { "webgl", WebGL },
++};
++
++static Cmd commands[] = {
++ { "clipboard", clipboard, ARGTYPE_INT },
++ { "find", find, ARGTYPE_INT },
++ { "inject", injectjs, ARGTYPE_STR },
++ { "loaduri", loaduri, ARGTYPE_STR },
++ { "reload", reload, ARGTYPE_INT },
++ { "scrollh", scrollh, ARGTYPE_INT },
++ { "scrollv", scrollv, ARGTYPE_INT },
++ { "showcert", showcert, ARGTYPE_NIL },
++ { "spawn", spawn, ARGTYPE_STR },
++ { "stop", stop, ARGTYPE_NIL },
++ { "toggle", togglewrapper, ARGTYPE_STR },
++ { "togglecookies", togglecookiepolicy, ARGTYPE_NIL },
++ { "togglefullscreen", togglefullscreen, ARGTYPE_NIL },
++ { "toggleinspector", toggleinspector, ARGTYPE_NIL },
++ { "zoom", zoom, ARGTYPE_INT },
++};
++
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+
+_AT_@ -351,6 +418,7 @@ setup(void)
+ cookiefile = buildfile(cookiefile);
+ scriptfile = buildfile(scriptfile);
+ certdir = buildpath(certdir);
++ fifodir = buildpath(fifodir);
+ if (curconfig[Ephemeral].val.i)
+ cachedir = NULL;
+ else
+_AT_@ -1080,9 +1148,15 @@ destroyclient(Client *c)
+ void
+ cleanup(void)
+ {
++ GError *error = NULL;
++
+ while (clients)
+ destroyclient(clients);
+
++ if (fifof != NULL)
++ if (!g_file_delete(fifof, NULL, &error))
++ g_warning("cleanup: couldn't delete fifo: %s
", error->message);
++
+ close(spair[0]);
+ close(spair[1]);
+ g_free(cookiefile);
+_AT_@ -1874,6 +1948,141 @@ msgext(Client *c, char type, const Arg *a)
+ c->pageid, type, a->i, ret);
+ }
+
++gboolean
++init_fifo(Client *c)
++{
++ gboolean r = FALSE;
++ char *path = g_strconcat(fifodir, "/", winid, NULL);
++
++ if (path) {
++ if (g_file_test(path, G_FILE_TEST_EXISTS) && unlink(path))
++ fprintf(stderr, "surf: couldn't unlink old fifo: %s
", path);
++
++ if (!mkfifo(path, 0600)) {
++ r = start_fifo(c, path);
++ } else {
++ fprintf(stderr, "init_fifo: couldn't create fifo: %s
", path);
++ r = FALSE;
++ }
++ }
++
++
++ // fifo info no longer needed
++ g_free(fifodir);
++ if (path)
++ g_free(path);
++
++ return r;
++}
++
++gboolean
++start_fifo(Client *c, char *path)
++{
++ GError *error = NULL;
++ GFileIOStream *fs;
++ GOutputStream *os;
++ GDataInputStream *is;
++ fifof = g_file_new_for_path (path);
++
++ /* open in read/write so no blocking occurs */
++ fs = g_file_open_readwrite(fifof, NULL, &error);
++ if (!fs) {
++ fprintf(stderr, "surf: can't open: %s
", error->message);
++ g_error_free(error);
++ return FALSE;
++ }
++
++ os = g_io_stream_get_output_stream(G_IO_STREAM(fs));
++ if (!g_output_stream_close(os, NULL, &error)) {
++ fprintf(stderr, "start_fifo: failed to close write end: %s
",
++ error->message);
++ g_error_free(error);
++ return FALSE;
++ }
++
++ is = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(fs)));
++
++ g_data_input_stream_read_line_async(is, G_PRIORITY_DEFAULT, NULL,
++ &fifo_read_cb, c);
++
++ g_setenv("SURF_FIFO", path, TRUE);
++
++ return TRUE;
++}
++
++void
++fifo_read_cb(GObject *f, GAsyncResult *r, gpointer d)
++{
++ Client *c = (Client *)d;
++ GDataInputStream *s = (GDataInputStream *)f;
++ GError *error = NULL;
++ gsize length;
++ gchar *rest;
++
++ gchar *line = g_data_input_stream_read_line_finish(s, r, &length, &error);
++ if (error) {
++ fprintf(stderr, "fifo_read_cb: error reading: %s
", error->message);
++ return;
++ }
++
++ if (!line)
++ return;
++
++ line = strtok_r(line, " ", &rest);
++
++ dispatchcmd(c, line, rest);
++
++ g_data_input_stream_read_line_async(s, G_PRIORITY_DEFAULT, NULL,
++ &fifo_read_cb, c);
++}
++
++void
++dispatchcmd(Client *c, char *cmd, char *a)
++{
++ Arg arg;
++ int i;
++
++ for (i = 0; i < LENGTH(commands); i++) {
++ if (strcmp(cmd, commands[i].cmd) == 0) {
++ switch (commands[i].t) {
++ case ARGTYPE_STR: arg = (Arg)(const void *)a; break;
++ case ARGTYPE_INT: arg = (Arg)atoi(a); break;
++ case ARGTYPE_FLT: arg = (Arg)(float)atof(a); break;
++ case ARGTYPE_NIL: arg = (Arg)0; break;
++ }
++
++ if (commands[i].t == ARGTYPE_INT) {
++ printf("%i
", arg.i);
++ }
++ commands[i].func(c, (const Arg *)&arg);
++ return;
++ }
++ }
++
++ fprintf(stderr, "%s: no such command
", cmd);
++}
++
++void
++injectjs(Client *c, const Arg *a)
++{
++ evalscript(c, "%s", (char *)a->v);
++}
++
++void
++togglewrapper(Client *c, const Arg *a)
++{
++ int i;
++
++ for (i = 0; i < LENGTH(paramnames); i++) {
++ if (strcmp(paramnames[i].p, (char *)a->v) == 0) {
++ Arg targ = (Arg)(const void *)paramnames[i].pv;
++ return toggle(c, &targ);
++ }
++ }
++
++ fprintf(stderr, "toggle: no such setting '%s'", (char *)a->v);
++}
++
+ void
+ scrollv(Client *c, const Arg *a)
+ {
+_AT_@ -2123,6 +2332,7 @@ main(int argc, char *argv[])
+ setup();
+ c = newclient(NULL);
+ showview(NULL, c);
++ init_fifo(c);
+
+ loaduri(c, &arg);
+ updatetitle(c);
+--
+2.35.1
+
Received on Fri Mar 11 2022 - 00:59:40 CET

This archive was generated by hypermail 2.3.0 : Fri Mar 11 2022 - 01:00:55 CET