From 96d49430705d94a7e28126ccf19c56645c6e517e Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 10 Dec 2020 17:53:44 +0300 Subject: [PATCH] Use recfile and TAI64N --- README | 6 ++-- go.mod | 6 ++-- go.sum | 21 ++++++++++---- main.go | 85 +++++++++++++++++++++++++++++++++++++-------------------- 4 files changed, 77 insertions(+), 41 deletions(-) diff --git a/README b/README index 053829e..7ab9f86 100644 --- a/README +++ b/README @@ -5,9 +5,9 @@ Also it calculates BLAKE2b checksum, replying with it in the answer. You can upload files with curl: - curl -F fileupload=@somedata.tar.gpg http://localhost:8086/upload/ - - curl -F fileupload=@somedata.tar.gpg -F comment="optional comment" http://localhost:8086/upload/ + curl -F file=@somedata.tar.gpg \ + [ -F comment="optional comment" ] \ + http://localhost:8086/upload/ You can verify integrity locally: diff --git a/go.mod b/go.mod index 0a06b73..4d9fe3c 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module go.stargrave.org/uploader go 1.12 require ( - golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 - golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 + go.cypherpunks.ru/recfile v0.3.0 + go.cypherpunks.ru/tai64n v0.1.0 + golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 + golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 ) diff --git a/go.sum b/go.sum index 045ad07..7bb608c 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,19 @@ +go.cypherpunks.ru/recfile v0.3.0 h1:aZRMMst8hoNOIhGjCA/VxjTN5VBSEN4W4zyhWF/7xSU= +go.cypherpunks.ru/recfile v0.3.0/go.mod h1:p1ZUMeyQQbQg+ICtKH3+Zt59QLI0tCZYZj/75Vp1buk= +go.cypherpunks.ru/tai64n v0.1.0 h1:XT1ys6lbo4/bjDQpMA8Xu5TCx6Y6aAYYYn5G0quE8sk= +go.cypherpunks.ru/tai64n v0.1.0/go.mod h1:mjuUq/ZQAOEKvzAAl25RIrN6JExWA4fRkOs7o7OVvYE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604= +golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go index a4b0449..030cb1f 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ package main import ( "bufio" + "bytes" "encoding/base64" "encoding/hex" "flag" @@ -32,16 +33,19 @@ import ( "net/http" "os" "os/exec" + "strconv" "strings" "time" + "go.cypherpunks.ru/recfile" + "go.cypherpunks.ru/tai64n" "golang.org/x/crypto/blake2b" "golang.org/x/net/netutil" ) const ( WriteBufSize = 1 << 20 - FileFieldName = "fileupload" + FileFieldName = "file" CommentFieldName = "comment" SendmailCmd = "/usr/sbin/sendmail" @@ -52,12 +56,14 @@ var ( Upload
 Example command line usage:
-  curl -F fileupload=@somedata.tar.gpg [-F comment="optional comment"] http://.../upload/
-  b2sum -a blake2b somedata.tar.gpg
+
+    $ curl -F file=@somedata.tar.gpg [-F comment="optional comment"] http://.../upload/
+    $ b2sum -a blake2b somedata.tar.gpg # to verify checksum
 
-
- +
+
+

`)) @@ -65,10 +71,18 @@ Example command line usage: NotifyToAddr *string ) -func notify(filename, timestamp string, size int64, comment string) { +func notify(tai, filename string, size int64, comment string) { if *NotifyToAddr == "" { return } + var rec bytes.Buffer + w := recfile.NewWriter(&rec) + w.WriteFields( + recfile.Field{Name: "TAI64N", Value: tai}, + recfile.Field{Name: "Size", Value: strconv.FormatInt(size, 10)}, + recfile.Field{Name: "Filename", Value: filename}, + ) + w.WriteFieldMultiline("Comment", strings.Split(comment, "\n")) cmd := exec.Command(SendmailCmd, *NotifyToAddr) cmd.Stdin = io.MultiReader( strings.NewReader(fmt.Sprintf( @@ -82,16 +96,9 @@ Content-Transfer-Encoding: base64 `, *NotifyFromAddr, *NotifyToAddr, - mime.BEncoding.Encode("UTF-8", fmt.Sprintf( - "%s (%d KiB)", filename, size/1024, - )), + mime.BEncoding.Encode("UTF-8", fmt.Sprintf("%s (%d KiB)", filename, size/1024)), )), - strings.NewReader(base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf( - "Timestamp: %s\nSize: %d bytes\nComment: %s\n", - timestamp, - size, - comment, - )))), + strings.NewReader(base64.StdEncoding.EncodeToString(rec.Bytes())), ) cmd.Run() } @@ -122,53 +129,71 @@ func upload(w http.ResponseWriter, r *http.Request) { if err != nil { panic(err) } - fn := time.Now().Format(time.RFC3339Nano) + t := time.Now() + ts := new(tai64n.TAI64N) + tai64n.FromTime(t, ts) + tai := ts.Encode()[1:] fnOrig := p.FileName() - fd, err := os.OpenFile(fn+".part", os.O_WRONLY|os.O_CREATE, 0600) + fd, err := os.OpenFile(tai+".part", os.O_WRONLY|os.O_CREATE, 0600) if err != nil { - log.Println(r.RemoteAddr, fn, fnOrig, err) + log.Println(r.RemoteAddr, tai, fnOrig, err) return } fdBuf := bufio.NewWriterSize(fd, WriteBufSize) mw := io.MultiWriter(fdBuf, h) n, err := io.Copy(mw, p) if err != nil { - log.Println(r.RemoteAddr, fn, fnOrig, err) + log.Println(r.RemoteAddr, tai, fnOrig, err) fd.Close() return } if n == 0 { - log.Println(r.RemoteAddr, fn, fnOrig, "empty") - os.Remove(fn + ".part") + log.Println(r.RemoteAddr, tai, fnOrig, "empty") + os.Remove(tai + ".part") fd.Close() fmt.Fprintf(w, "Empty file") return } if err = fdBuf.Flush(); err != nil { - log.Println(r.RemoteAddr, fn, fnOrig, err) + log.Println(r.RemoteAddr, tai, fnOrig, err) + fd.Close() + return + } + if err = fd.Sync(); err != nil { + log.Println(r.RemoteAddr, tai, fnOrig, err) fd.Close() return } fd.Close() sum := hex.EncodeToString(h.Sum(nil)) - if err = os.Rename(fn+".part", fn); err != nil { - log.Println(r.RemoteAddr, fn, fnOrig, n, sum, err) + if err = os.Rename(tai+".part", tai); err != nil { + log.Println(r.RemoteAddr, tai, fnOrig, n, sum, err) + return + } + var rec bytes.Buffer + wr := recfile.NewWriter(&rec) + if _, err = wr.WriteFields( + recfile.Field{Name: "TAI64N", Value: tai}, + recfile.Field{Name: "Size", Value: strconv.FormatInt(n, 10)}, + recfile.Field{Name: "Checksum", Value: sum}, + ); err != nil { + log.Println(r.RemoteAddr, tai, fnOrig, n, sum, err) return } - fmt.Fprintf(w, "Timestamp: %s\nBytes: %d\nBLAKE2b: %s\n", fn, n, sum) - log.Println(r.RemoteAddr, fn, fnOrig, n, sum) + io.Copy(w, &rec) + log.Println(r.RemoteAddr, tai, fnOrig, n, sum) p, err = mr.NextPart() if err != nil || p.FormName() != CommentFieldName { - go notify(fnOrig, fn, n, "") + go notify(fnOrig, tai, n, "") return } comment, err := ioutil.ReadAll(p) if err != nil || len(comment) == 0 { - go notify(fnOrig, fn, n, "") + go notify(tai, fnOrig, n, "") return } - ioutil.WriteFile(fn+".txt", comment, os.FileMode(0600)) - go notify(fnOrig, fn, n, string(comment)) + ioutil.WriteFile(tai+".txt", comment, os.FileMode(0600)) + go notify(tai, fnOrig, n, string(comment)) } func main() { -- 2.44.0