From bcc1c2d9dd7fefa538647c0d4e9e621511f1fde6 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Tue, 7 Oct 2025 08:31:39 -0700 Subject: Bring back pbkdf2 --- tools/hole/hole.go | 94 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 66 insertions(+), 28 deletions(-) (limited to 'tools/hole') diff --git a/tools/hole/hole.go b/tools/hole/hole.go index d701c40..c6946f0 100644 --- a/tools/hole/hole.go +++ b/tools/hole/hole.go @@ -1,36 +1,54 @@ +// The hole command is a CLI uploader tool for the roseh.moe wormhole. +// +// # Magic wormhole +// +// The name is inspired by the original "magic wormhole" library. The goal is to +// get a file from one computer to another without a USB stick, Including cases +// where scp might not be available. This includes transferring files to your +// phone, for example, although a USB cord might still be more convenient when +// moving many files. It should also work over restrictive firewalls. You should +// be able to use the wormhole as long as you can access http://roseh.moe in +// a browser. +// +// # Usage example +// +// The following shows a typical interaction with the tool +// +// $ hole file.pdf +// https://roseh.moe/wormhole/dv-32-ethos-aztec-shako-spoils-2y-dwarf-sand-any +// Waiting for upload... +// +// +// Then, on another machine: +// +// $ curl https://roseh.moe/wormhole/dv-32-ethos-aztec-shako-spoils-2y-dwarf-sand-any > file.pdf +// +// # Web interface +// +// There's also a web interface available for the wormhole, available at +// https://roseh.moe/wormhole. package main import ( - "crypto/rand" - "encoding/binary" "flag" "fmt" "io" "mime/multipart" "net/http" "os" - "strings" - "gitlab.com/rhogenson/roseh.moe/internal/wordlist" + "gitlab.com/rhogenson/roseh.moe/internal/hole" ) var url = flag.String("url", "https://roseh.moe", "server URL") -func makeHole() string { - const nWords = 10 - buf := make([]byte, 2*nWords) - rand.Read(buf) - words := make([]string, nWords) - for i := range words { - words[i] = wordlist.Words[binary.NativeEndian.Uint16(buf[2*i:])&0x1fff] - } - return strings.Join(words, "-") -} - -func hole() error { +func upload() error { args := flag.Args() - if len(args) != 1 { - return fmt.Errorf("usage error") + if len(args) == 0 { + return fmt.Errorf("usage error: missing filename") + } + if len(args) > 1 { + return fmt.Errorf("usage error: too many positional arguments") } fileName := args[0] f, err := os.Open(fileName) @@ -38,18 +56,19 @@ func hole() error { return err } defer f.Close() - hole := makeHole() + hole := hole.New() fmt.Println(*url + "/wormhole/" + hole) + fmt.Fprintln(os.Stderr, "Waiting for upload...") resp, err := http.Get(*url + "/wormhole/" + hole + "/ready") if err != nil { - return err + return fmt.Errorf("check wormhole ready: %s", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("%s", resp.Status) + return fmt.Errorf("check wormhole ready: status: %s", resp.Status) } if _, err := io.Copy(io.Discard, resp.Body); err != nil { - return err + return fmt.Errorf("check wormhole ready: read response: %s", err) } pipeReader, pipeWriter := io.Pipe() multipartWriter := multipart.NewWriter(pipeWriter) @@ -57,15 +76,15 @@ func hole() error { defer pipeWriter.Close() part, err := multipartWriter.CreateFormFile("file", fileName) if err != nil { - fmt.Fprintln(os.Stderr, err) + pipeWriter.CloseWithError(fmt.Errorf("create multipart reader: %s", err)) return } if _, err := io.Copy(part, f); err != nil { - fmt.Fprintln(os.Stderr, err) + pipeWriter.CloseWithError(fmt.Errorf("write body: %s", err)) return } if err := multipartWriter.Close(); err != nil { - fmt.Fprintln(os.Stderr, err) + pipeWriter.CloseWithError(fmt.Errorf("write trailer: %s", err)) return } }() @@ -75,7 +94,7 @@ func hole() error { } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return fmt.Errorf("%s", resp.Status) + return fmt.Errorf("upload: status: %s", resp.Status) } io.Copy(os.Stderr, resp.Body) fmt.Fprintln(os.Stderr) @@ -83,9 +102,28 @@ func hole() error { } func main() { + flag.Usage = func() { + fmt.Fprint(os.Stderr, `Usage: hole FILE +Create a one-time wormhole that allows a specific client to download a +file. Prints the URL to download the file and then hangs until the file +is downloaded. + +Example: + $ hole file.pdf + https://roseh.moe/wormhole/dv-32-ethos-aztec-shako-spoils-2y-dwarf-sand-any + Waiting for upload... + + +Then, on another machine: + $ curl https://roseh.moe/wormhole/dv-32-ethos-aztec-shako-spoils-2y-dwarf-sand-any > file.pdf + +Flags: +`) + flag.PrintDefaults() + } flag.Parse() - if err := hole(); err != nil { - fmt.Fprintln(os.Stderr, err) + if err := upload(); err != nil { + fmt.Fprintf(os.Stderr, "hole: %s\n", err) os.Exit(1) } } -- cgit v1.3.1