diff options
author | Profpatsch <mail@profpatsch.de> | 2020-07-03 13:11:03 +0200 |
---|---|---|
committer | Profpatsch <mail@profpatsch.de> | 2020-07-06 20:13:42 +0200 |
commit | 97f05263ef490a063a33733d7ea607411a097df8 (patch) | |
tree | f1617705e22437c908459e1de059993bcab09ed3 /pkgs/profpatsch/xdg-open/default.nix | |
parent | e409df3861f48de44d0e37277ce007e348a7a0dc (diff) |
pkgs/profpatsch/xdg-open: Prepare decoding http urls
I want to be able to open http(s) links that are e.g. images directly in the right application. Aka web urls should be transparent, instead of always opening everthing in the browser. This adds some silly ways of connecting to the server and parsing out the headers, in order to fetch the content-type.
Diffstat (limited to 'pkgs/profpatsch/xdg-open/default.nix')
-rw-r--r-- | pkgs/profpatsch/xdg-open/default.nix | 139 |
1 files changed, 138 insertions, 1 deletions
diff --git a/pkgs/profpatsch/xdg-open/default.nix b/pkgs/profpatsch/xdg-open/default.nix index a4aaff97..e73f8093 100644 --- a/pkgs/profpatsch/xdg-open/default.nix +++ b/pkgs/profpatsch/xdg-open/default.nix @@ -1,9 +1,25 @@ -{ pkgs, getBins, importDhall2, writeExecline, dhall, buildDhallPackage, writeRustSimple, el-exec }: +{ pkgs, getBins, +importDhall2, +writeExecline, +dhall, +buildDhallPackage, +runExeclineLocal, +writeRustSimple, +netencode-rs, +record-get, +el-exec +}: let lib = pkgs.lib; bins = getBins pkgs.libnotify [ "notify-send" ] // getBins pkgs.file [ "file" ] + // getBins pkgs.coreutils [ "printf" "ln" "echo" ] + // getBins pkgs.fdtools [ "multitee" ] + // getBins pkgs.s6 [ "s6-ioconnect" ] + // getBins pkgs.s6-portable-utils [ "s6-test" ] + // getBins pkgs.s6-networking [ "s6-tcpclient" ] + // getBins pkgs.netcat-openbsd [ "nc" ] // getBins pkgs.dmenu [ "dmenu" "dmenu_path" ] # TODO: make sure these are the ones from the environment // getBins pkgs.emacs [ "emacsclient" ] @@ -122,6 +138,119 @@ let ; }; + httparse = pkgs.buildRustCrate { + pname = "httparse"; + version = "1.3.4"; + crateName = "httparse"; + sha256 = "0dggj4s0cq69bn63q9nqzzay5acmwl33nrbhjjsh5xys8sk2x4jw"; + }; + + stderr-tee = writeExecline "stderr-tee" {} [ + "pipeline" [ bins.multitee "0-1,2" ] "$@" + ]; + + stderr-prog = writeExecline "stderr-prog" {} [ + "foreground" [ bins.echo "$@" ] + "$@" + ]; + + http-request = writeExecline "http-request-for-url" { } [ + "importas" "-i" "protocol" "protocol" + "ifelse" [ bins.s6-test "$protocol" "=" "http" ] [ (http-https-request false) ] + "ifelse" [ bins.s6-test "$protocol" "=" "https" ] [ (http-https-request true) ] + eprintf "protocol \${protocol} not supported" + ]; + + http-https-request = isHttps: writeExecline "http-https-request" { } ([ + "multisubstitute" [ + "importas" "-ui" "port" "port" + "importas" "-ui" "host" "host" + "importas" "-ui" "path" "path" + ] + "pipeline" [ + bins.printf (lib.concatStringsSep "\r\n" [ + ''HEAD %s HTTP/1.1'' + ''Host: %s'' + ''User-Agent: lol'' + ''Accept: */*'' + "" + "" + ]) "$path" "$host" + ] + bins.nc + ] ++ lib.optional isHttps "-c" ++ [ + "-N" "$host" "$port" + ]); + + printenv = writeRustSimple "printenv" {} + (pkgs.writeText "printenv.rs" '' + use std::io::Write; + use std::os::unix::ffi::OsStrExt; + fn main() -> std::io::Result<()> { + let usage = || { + eprintln!("usage: printenv VAR"); + std::process::exit(1) + }; + let mut args = std::env::args_os(); + let _ = args.next().unwrap_or_else(usage); + let var = args.next().unwrap_or_else(usage); + match std::env::var_os(&var) { + None => { + let mut err = std::io::stderr(); + err.write_all("env variable ".as_bytes())?; + err.write_all(var.as_bytes())?; + err.write_all(" does not exist\n".as_bytes())?; + }, + Some(stuff) => std::io::stdout().write_all(stuff.as_bytes())? + } + Ok(()) + } + ''); + + assert-printf = writeExecline "assert-printf" { argMode = "env"; } [ + "ifelse" [ "runblock" "2" ] + [ "runblock" "-r" "2" ] + "fdmove" "-c" "1" "2" + "runblock" "1" bins.printf + ]; + + as-stdin = writeExecline "as-stdin" { readNArgs = 1; } [ + "pipeline" [ printenv "$1" ] "$@" + ]; + + read-headers-and-follow-redirect = writeExecline "read-headers-and-follow-redirect" { readNArgs = 1; } + (let go = writeExecline "go" {} [ + "pipeline" [ http-request ] + "pipeline" [ read-http ] + record-get [ "status" "status-text" "headers" ] + "importas" "-ui" "status" "status" + # TODO: a test util for netencode values + "ifelse" [ bins.s6-test "$status" "=" "n6:301," ] + # retry the redirection location + [ as-stdin "headers" + record-get [ "Location" ] + "importas" "-ui" "Location" "Location" + "export" "host" "$Location" + "if" [ "echo" "redirected to \${Location}" ] + # save path, which would be overwritten by mini-url + "importas" "old-path" "path" + mini-url "$Location" + "export" "path" "$old-path" + "$0" + ] + printenv "headers" + ]; + in [ + mini-url "$1" + go + ]); + + + read-http = writeRustSimple "read-http" { + dependencies = [ httparse netencode-rs ]; + buildInputs = [ pkgs.skalibs ]; + } ./read-http.rs; + mini-url = writeRustSimple "mini-url" { dependencies = [ el-exec ]; buildInputs = [ pkgs.skalibs ]; @@ -130,10 +259,18 @@ let verbose = true; } ./mini-url.rs; + eprintf = writeExecline "eprintf" {} [ + "fdmove" "-c" "1" "2" bins.printf "%s" "$@" + ]; + in { inherit xdg-open Prelude + read-headers-and-follow-redirect mini-url + assert-printf + as-stdin + printenv ; } |