commit 48263a781ea60559d2fc559e831e69c13f78139a
Author: avalonwilliams <[email protected]>
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
@@ -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
@@ -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 <[email protected]>
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
@@ -0,0 +1,309 @@
+From c5c1646470c4a278a9e44dc3934b4e0346518d40 Mon Sep 17 00:00:00 2001
+From: avalonwilliams <[email protected]>
+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
+@@ -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
+@@ -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>
+@@ -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);
+@@ -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];
+@@ -255,6 +282,7 @@ static Parameter *curconfig;
+ static int modparams[ParameterLast];
+ static int spair[2];
+ char *argv0;
++static GFile *fifof;
+ 
+ static ParamName loadtransient[] = {
+       Certificate,
+@@ -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"
+ 
+@@ -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
+@@ -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);
+@@ -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)
+ {
+@@ -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
+


Reply via email to