surf-fifo-20220310-c5c1646.diff (8358B)
1 From c5c1646470c4a278a9e44dc3934b4e0346518d40 Mon Sep 17 00:00:00 2001 2 From: avalonwilliams <avalonwilliams@protonmail.com> 3 Date: Wed, 9 Mar 2022 23:53:08 -0500 4 Subject: [PATCH] fifo patch 5 6 Adds a small command language for remote control of surf through 7 a fifo pipe, allowing for more complex scripts and features to be 8 added through shell scripts. Also adds a javascript injection function 9 that you can bind keys to. 10 --- 11 config.def.h | 1 + 12 surf.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++ 13 2 files changed, 211 insertions(+) 14 15 diff --git a/config.def.h b/config.def.h 16 index 1355ba3..dcc8d64 100644 17 --- a/config.def.h 18 +++ b/config.def.h 19 @@ -6,6 +6,7 @@ static char *styledir = "~/.surf/styles/"; 20 static char *certdir = "~/.surf/certificates/"; 21 static char *cachedir = "~/.surf/cache/"; 22 static char *cookiefile = "~/.surf/cookies.txt"; 23 +static char *fifodir = "~/.surf/fifo/"; 24 25 /* Webkit default features */ 26 /* Highest priority value will be used. 27 diff --git a/surf.c b/surf.c 28 index 03d8242..327698e 100644 29 --- a/surf.c 30 +++ b/surf.c 31 @@ -17,6 +17,8 @@ 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 +#include <sys/types.h> 36 +#include <sys/stat.h> 37 38 #include <gdk/gdk.h> 39 #include <gdk/gdkkeysyms.h> 40 @@ -141,6 +143,24 @@ typedef struct { 41 regex_t re; 42 } SiteSpecific; 43 44 +typedef enum { 45 + ARGTYPE_INT, 46 + ARGTYPE_FLT, 47 + ARGTYPE_STR, 48 + ARGTYPE_NIL, 49 +} ArgType; 50 + 51 +typedef struct { 52 + char *cmd; 53 + void (*func)(Client *c, const Arg *a); 54 + ArgType t; 55 +} Cmd; 56 + 57 +typedef struct { 58 + char *p; 59 + ParamName pv; 60 +} ParamMap; 61 + 62 /* Surf */ 63 static void die(const char *errstr, ...); 64 static void usage(void); 65 @@ -239,6 +259,13 @@ static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h); 66 static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h); 67 static void clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h); 68 69 +static gboolean init_fifo(Client *c); 70 +static gboolean start_fifo(Client *c, char *path); 71 +static void fifo_read_cb(GObject *f, GAsyncResult *r, gpointer d); 72 +static void dispatchcmd(Client *c, char *cmd, char *a); 73 +static void injectjs(Client *c, const Arg *a); 74 +static void togglewrapper(Client *c, const Arg *a); 75 + 76 static char winid[64]; 77 static char togglestats[11]; 78 static char pagestats[2]; 79 @@ -255,6 +282,7 @@ static Parameter *curconfig; 80 static int modparams[ParameterLast]; 81 static int spair[2]; 82 char *argv0; 83 +static GFile *fifof; 84 85 static ParamName loadtransient[] = { 86 Certificate, 87 @@ -298,6 +326,45 @@ static ParamName loadfinished[] = { 88 ParameterLast 89 }; 90 91 +static ParamMap paramnames[] = { 92 + { "autoplay", MediaManualPlay }, 93 + { "caret", CaretBrowsing }, 94 + { "frameflat", FrameFlattening }, 95 + { "geolocation", Geolocation }, 96 + { "hidebg", HideBackground }, 97 + { "images", LoadImages }, 98 + { "indicators", ShowIndicators }, 99 + { "java", Java }, 100 + { "js", JavaScript }, 101 + { "kiosk", KioskMode }, 102 + { "microphone", AccessMicrophone }, 103 + { "scrollbars", ScrollBars }, 104 + { "smoothscroll", SmoothScrolling }, 105 + { "spellcheck", SpellChecking }, 106 + { "stricttls", StrictTLS }, 107 + { "style", Style }, 108 + { "webcam", AccessWebcam }, 109 + { "webgl", WebGL }, 110 +}; 111 + 112 +static Cmd commands[] = { 113 + { "clipboard", clipboard, ARGTYPE_INT }, 114 + { "find", find, ARGTYPE_INT }, 115 + { "inject", injectjs, ARGTYPE_STR }, 116 + { "loaduri", loaduri, ARGTYPE_STR }, 117 + { "reload", reload, ARGTYPE_INT }, 118 + { "scrollh", scrollh, ARGTYPE_INT }, 119 + { "scrollv", scrollv, ARGTYPE_INT }, 120 + { "showcert", showcert, ARGTYPE_NIL }, 121 + { "spawn", spawn, ARGTYPE_STR }, 122 + { "stop", stop, ARGTYPE_NIL }, 123 + { "toggle", togglewrapper, ARGTYPE_STR }, 124 + { "togglecookies", togglecookiepolicy, ARGTYPE_NIL }, 125 + { "togglefullscreen", togglefullscreen, ARGTYPE_NIL }, 126 + { "toggleinspector", toggleinspector, ARGTYPE_NIL }, 127 + { "zoom", zoom, ARGTYPE_INT }, 128 +}; 129 + 130 /* configuration, allows nested code to access above variables */ 131 #include "config.h" 132 133 @@ -351,6 +418,7 @@ setup(void) 134 cookiefile = buildfile(cookiefile); 135 scriptfile = buildfile(scriptfile); 136 certdir = buildpath(certdir); 137 + fifodir = buildpath(fifodir); 138 if (curconfig[Ephemeral].val.i) 139 cachedir = NULL; 140 else 141 @@ -1080,9 +1148,15 @@ destroyclient(Client *c) 142 void 143 cleanup(void) 144 { 145 + GError *error = NULL; 146 + 147 while (clients) 148 destroyclient(clients); 149 150 + if (fifof != NULL) 151 + if (!g_file_delete(fifof, NULL, &error)) 152 + g_warning("cleanup: couldn't delete fifo: %s\n", error->message); 153 + 154 close(spair[0]); 155 close(spair[1]); 156 g_free(cookiefile); 157 @@ -1874,6 +1948,141 @@ msgext(Client *c, char type, const Arg *a) 158 c->pageid, type, a->i, ret); 159 } 160 161 +gboolean 162 +init_fifo(Client *c) 163 +{ 164 + gboolean r = FALSE; 165 + char *path = g_strconcat(fifodir, "/", winid, NULL); 166 + 167 + if (path) { 168 + if (g_file_test(path, G_FILE_TEST_EXISTS) && unlink(path)) 169 + fprintf(stderr, "surf: couldn't unlink old fifo: %s\n", path); 170 + 171 + if (!mkfifo(path, 0600)) { 172 + r = start_fifo(c, path); 173 + } else { 174 + fprintf(stderr, "init_fifo: couldn't create fifo: %s\n", path); 175 + r = FALSE; 176 + } 177 + } 178 + 179 + 180 + // fifo info no longer needed 181 + g_free(fifodir); 182 + if (path) 183 + g_free(path); 184 + 185 + return r; 186 +} 187 + 188 +gboolean 189 +start_fifo(Client *c, char *path) 190 +{ 191 + GError *error = NULL; 192 + GFileIOStream *fs; 193 + GOutputStream *os; 194 + GDataInputStream *is; 195 + fifof = g_file_new_for_path (path); 196 + 197 + /* open in read/write so no blocking occurs */ 198 + fs = g_file_open_readwrite(fifof, NULL, &error); 199 + if (!fs) { 200 + fprintf(stderr, "surf: can't open: %s\n", error->message); 201 + g_error_free(error); 202 + return FALSE; 203 + } 204 + 205 + os = g_io_stream_get_output_stream(G_IO_STREAM(fs)); 206 + if (!g_output_stream_close(os, NULL, &error)) { 207 + fprintf(stderr, "start_fifo: failed to close write end: %s\n", 208 + error->message); 209 + g_error_free(error); 210 + return FALSE; 211 + } 212 + 213 + is = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_STREAM(fs))); 214 + 215 + g_data_input_stream_read_line_async(is, G_PRIORITY_DEFAULT, NULL, 216 + &fifo_read_cb, c); 217 + 218 + g_setenv("SURF_FIFO", path, TRUE); 219 + 220 + return TRUE; 221 +} 222 + 223 +void 224 +fifo_read_cb(GObject *f, GAsyncResult *r, gpointer d) 225 +{ 226 + Client *c = (Client *)d; 227 + GDataInputStream *s = (GDataInputStream *)f; 228 + GError *error = NULL; 229 + gsize length; 230 + gchar *rest; 231 + 232 + gchar *line = g_data_input_stream_read_line_finish(s, r, &length, &error); 233 + if (error) { 234 + fprintf(stderr, "fifo_read_cb: error reading: %s\n", error->message); 235 + return; 236 + } 237 + 238 + if (!line) 239 + return; 240 + 241 + line = strtok_r(line, " ", &rest); 242 + 243 + dispatchcmd(c, line, rest); 244 + 245 + g_data_input_stream_read_line_async(s, G_PRIORITY_DEFAULT, NULL, 246 + &fifo_read_cb, c); 247 +} 248 + 249 +void 250 +dispatchcmd(Client *c, char *cmd, char *a) 251 +{ 252 + Arg arg; 253 + int i; 254 + 255 + for (i = 0; i < LENGTH(commands); i++) { 256 + if (strcmp(cmd, commands[i].cmd) == 0) { 257 + switch (commands[i].t) { 258 + case ARGTYPE_STR: arg = (Arg)(const void *)a; break; 259 + case ARGTYPE_INT: arg = (Arg)atoi(a); break; 260 + case ARGTYPE_FLT: arg = (Arg)(float)atof(a); break; 261 + case ARGTYPE_NIL: arg = (Arg)0; break; 262 + } 263 + 264 + if (commands[i].t == ARGTYPE_INT) { 265 + printf("%i\n", arg.i); 266 + } 267 + commands[i].func(c, (const Arg *)&arg); 268 + return; 269 + } 270 + } 271 + 272 + fprintf(stderr, "%s: no such command\n", cmd); 273 +} 274 + 275 +void 276 +injectjs(Client *c, const Arg *a) 277 +{ 278 + evalscript(c, "%s", (char *)a->v); 279 +} 280 + 281 +void 282 +togglewrapper(Client *c, const Arg *a) 283 +{ 284 + int i; 285 + 286 + for (i = 0; i < LENGTH(paramnames); i++) { 287 + if (strcmp(paramnames[i].p, (char *)a->v) == 0) { 288 + Arg targ = (Arg)(const void *)paramnames[i].pv; 289 + return toggle(c, &targ); 290 + } 291 + } 292 + 293 + fprintf(stderr, "toggle: no such setting '%s'", (char *)a->v); 294 +} 295 + 296 void 297 scrollv(Client *c, const Arg *a) 298 { 299 @@ -2123,6 +2332,7 @@ main(int argc, char *argv[]) 300 setup(); 301 c = newclient(NULL); 302 showview(NULL, c); 303 + init_fifo(c); 304 305 loaduri(c, &arg); 306 updatetitle(c); 307 -- 308 2.35.1 309