diff options
Diffstat (limited to 'pkgs/profpatsch')
-rw-r--r-- | pkgs/profpatsch/default.nix | 9 | ||||
-rw-r--r-- | pkgs/profpatsch/xdg-open/default.nix | 139 | ||||
-rw-r--r-- | pkgs/profpatsch/xdg-open/read-http.rs | 56 | ||||
-rw-r--r-- | pkgs/profpatsch/xdg-open/xdg-open.dhall | 4 |
4 files changed, 206 insertions, 2 deletions
diff --git a/pkgs/profpatsch/default.nix b/pkgs/profpatsch/default.nix index c3f0d7e2..999382c0 100644 --- a/pkgs/profpatsch/default.nix +++ b/pkgs/profpatsch/default.nix @@ -220,10 +220,17 @@ in rec { rust-deps = (import ./rust-deps.nix { inherit (pkgs) buildRustCrate; }); - inherit (import ./xdg-open { inherit pkgs getBins importDhall2 writeExecline dhall buildDhallPackage writeRustSimple el-exec; }) + inherit (import ./xdg-open { inherit pkgs getBins importDhall2 writeExecline dhall buildDhallPackage runExeclineLocal netencode-rs writeRustSimple record-get el-exec; }) xdg-open + config Prelude + httparse + get-http-content-type + read-headers-and-follow-redirect mini-url + assert-printf + as-stdin + printenv ; inherit (import ./netencode { inherit pkgs writeRustSimpleLib writeRustSimple el-semicolon el-exec; }) 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 ; } diff --git a/pkgs/profpatsch/xdg-open/read-http.rs b/pkgs/profpatsch/xdg-open/read-http.rs new file mode 100644 index 00000000..9fe8d6a9 --- /dev/null +++ b/pkgs/profpatsch/xdg-open/read-http.rs @@ -0,0 +1,56 @@ +extern crate httparse; +extern crate netencode; + +use std::os::unix::io::FromRawFd; +use std::io::Read; +use std::io::Write; + +use netencode::{encode, U}; + +fn main() -> std::io::Result<()> { + + fn die<T: std::fmt::Display>(msg: T) { + eprintln!("{}", msg); + std::process::exit(1); + } + + // max header size chosen arbitrarily + let mut headers = [httparse::EMPTY_HEADER; 128]; + let mut resp = httparse::Response::new(&mut headers); + let mut buf = vec![]; + std::io::stdin().read_to_end(&mut buf)?; + let res = resp.parse(&mut buf); + match res { + Err(err) => die(format!("http response error: {:?}", err)), + Ok(_start_of_body) => { + match resp.code { + Some(code) => write_dict(code, resp.reason, resp.headers)?, + None => die(format!("no http status")) + } + } + }; + Ok(()) +} + +fn write_dict<'buf>(code: u16, reason: Option<&'buf str>, headers: &mut [httparse::Header<'buf>]) -> std::io::Result<()> { + let mut http = vec![ + ("status", Box::new(U::N6(code as u64))), + ]; + + if let Some(t) = reason { + http.push(("status-text", Box::new(U::Text(t.as_bytes())))) + }; + + http.push(("headers", Box::new(U::Record( + headers.iter_mut().map( + |httparse::Header { name, value }| + (*name, + Box::new(U::Binary(value))) + ).collect::<Vec<_>>() + )))); + + encode( + &mut std::io::stdout(), + U::Record(http) + ) +} diff --git a/pkgs/profpatsch/xdg-open/xdg-open.dhall b/pkgs/profpatsch/xdg-open/xdg-open.dhall index a7daebe3..03f168c3 100644 --- a/pkgs/profpatsch/xdg-open/xdg-open.dhall +++ b/pkgs/profpatsch/xdg-open/xdg-open.dhall @@ -91,6 +91,10 @@ let xdg-open = set -e file="$1" + mime= + + # match on protocols + # if you want to match files reliably, start with file:// case "$file" in ${prettyLines { indent = 2 |