From 0e006de337398d557b290d727f40e9303a5ababf Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 11 Feb 2022 16:24:09 +0300 Subject: [PATCH] Texinfo documentation, website and asciicasts --- INSTALL | 58 +------------------------ PROTOCOL | 8 ---- README | 43 ------------------- asciicast.tmpl | 16 +++++++ contrib/clean.sh | 6 +++ doc/.gitignore | 1 + doc/asciicast.texi | 22 ++++++++++ doc/examples.texi | 55 ++++++++++++++++++++++++ doc/features.texi | 31 ++++++++++++++ doc/index.texi | 30 +++++++++++++ doc/install.texi | 104 +++++++++++++++++++++++++++++++++++++++++++++ doc/protocol.texi | 16 +++++++ doc/style.css | 5 +++ doc/www.do | 15 +++++++ main.go | 45 +++++++++++++++++++- 15 files changed, 346 insertions(+), 109 deletions(-) delete mode 100644 PROTOCOL create mode 100644 asciicast.tmpl create mode 100755 contrib/clean.sh create mode 100644 doc/.gitignore create mode 100644 doc/asciicast.texi create mode 100644 doc/examples.texi create mode 100644 doc/features.texi create mode 100644 doc/index.texi create mode 100644 doc/install.texi create mode 100644 doc/protocol.texi create mode 100644 doc/style.css create mode 100644 doc/www.do diff --git a/INSTALL b/INSTALL index 28a9b0b..1703928 100644 --- a/INSTALL +++ b/INSTALL @@ -1,57 +1 @@ -Install paster itself: - - $ go get go.stargrave.org/paster - -Add "paster" user and "pastes" directory, also accessible by HTTP service: - - # pw useradd paster -s /usr/sbin/nologin -w no -d /path/to/pastes - # mkdir /path/to/pastes - # echo "Paste service" > /path/to/pastes/index.html - # chown -R paster:lighttpd pastes - # chmod 2750 pastes - # chmod 640 /path/to/pastes/index.html - -Create daemontools+ucspi-tcp service: - - # mkdir -p /var/service/.paster/log/main - # cat > /var/service/.paster/run <&1 - EOF - # cat > /var/service/.paster/log/run < $tmpl <&1 +Look for doc/install.texi. diff --git a/PROTOCOL b/PROTOCOL deleted file mode 100644 index 96ee59c..0000000 --- a/PROTOCOL +++ /dev/null @@ -1,8 +0,0 @@ -Protocol is very simple: bencoded dictionary is sent over TCP. - -* "v" key contains the data you want to paste -* optional "e" key, holding the desired filename extension, without the - leading dot, up to 9 characters long - -"hello world" => d1:v11:hello worlde -"http://example.com/" and "url" extension => d1:e3:url1:v18:http://example.come diff --git a/README b/README index d526416..e6a5978 100644 --- a/README +++ b/README @@ -1,45 +1,2 @@ go.stargrave.org/paster -- paste service daemon - -Are you tired of too complicated solutions even for the simple task like -paste storage? I too. That is why that paster daemon is here. - -* It uses file system for storing the pastes -* Pastes are shared through the external program (HTTP, FTP, Gopher, ...) -* Paste files have an extension (.txt by default), that can be overriden - for the given paste. So your HTTP service can answer with varying - Content-Types. You can share images for example, not only plaintext -* No excessive HTTP protocol: just send bencode-ed dictionary with the - data over the TCP -* Newline is appended for .txt/.url pastes, if it is missing -* SHA512/2 checksum is sent back to you, for integrity checking -* Intended to be run as a UCSPI-TCP service - (https://cr.yp.to/ucspi-tcp.html) under daemontools-like supervisor - (http://cr.yp.to/daemontools.html) -* You can clear an old ones with simple: find pastes -ctime XXX -delete - -With contrib/paster you can send the paste very easily: - - $ paster - something I want to send - whatever whenever - ^D - http://paster.example.com/4KEOLWCZY5CBVWDNT5TA.txt - 28d95ef0e8d6a4f4222d0e7eb2a23777aa99efb0794e535a0f4a55490705438f - - $ paster webp < some-image.webp - http://paster.example.com/KO5O7SJTUGBORVGOZBSA.webp - 7f53424fe50f1d70fa32763cde31335dc82fd63c975e8ab95f0bb4a6cd94fb1c - - $ paster some-other-image.webp - http://paster.example.com/O6D2O3N5HPH63ZFIYF4A.webp - https://paster.example.com/O6D2O3N5HPH63ZFIYF4A.webp - ftp://paster.example.com/pub/pastes/O6D2O3N5HPH63ZFIYF4A.webp - 2ffe10846ec637d29ab9145b98c3699653c01910bb6d9e00e41f7fe02c5882a8 - - $ grep whatever ... | paster - $ import png:- | paster png - $ import -define webp:lossless=true webp:- | paster webp - $ echo http://example.com | paster url - $ paster < /proc/cpuinfo - paster is free software: see the file COPYING for copying conditions. diff --git a/asciicast.tmpl b/asciicast.tmpl new file mode 100644 index 0000000..2238033 --- /dev/null +++ b/asciicast.tmpl @@ -0,0 +1,16 @@ + + + + asciicast + + + + + + + + diff --git a/contrib/clean.sh b/contrib/clean.sh new file mode 100755 index 0000000..a9148a9 --- /dev/null +++ b/contrib/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +find . -type f -mtime +1 \ + -and -not -name index.html \ + -and -not -name "asciinema-player-*" \ + -delete diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..2129d45 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +/paster.html diff --git a/doc/asciicast.texi b/doc/asciicast.texi new file mode 100644 index 0000000..2dc6be2 --- /dev/null +++ b/doc/asciicast.texi @@ -0,0 +1,22 @@ +@node Asciicast +@unnumbered Asciicast + +You can optionally automatically generate HTML pages for your +@file{.cast}s, if you copy +@url{https://github.com/asciinema/asciinema-player/releases, asciinema-player} +bundle to your HTTP server and specify its base name for +@option{-asciicast-path}: + +@example +$ v=v2.6.1 +$ u=https://github.com/asciinema/asciinema-player/releases/download/$v/ +$ for ext in css js ; do + wget -O /path/to/www/asciinema-player-$v.$ext $u/asciinema-player.$ext +done + +use $GOPATH/bin/paster -asciicast-path asciinema-player-v2.6.1 +@end example + +After that, additional @file{.cast.html} file will be generated during +upload each time, with the links to the @file{.cast} and the player. You +will also get those HTML URLs in the output. diff --git a/doc/examples.texi b/doc/examples.texi new file mode 100644 index 0000000..1de5e34 --- /dev/null +++ b/doc/examples.texi @@ -0,0 +1,55 @@ +@node Examples +@unnumbered Examples + +With @command{contrib/paster} you can send the paste very easily: + +@itemize + +@item +@example +$ paster +something I want to send +whatever whenever +^D +http://paster.example.com/4KEOLWCZY5CBVWDNT5TA.txt +SHA512/2: 28d95ef0e8d6a4f4222d0e7eb2a23777aa99efb0794e535a0f4a55490705438f +@end example + +@item With overriden file extension +@example +$ paster webp < some-image.webp +http://paster.example.com/KO5O7SJTUGBORVGOZBSA.webp +SHA512/2: 7f53424fe50f1d70fa32763cde31335dc82fd63c975e8ab95f0bb4a6cd94fb1c +@end example + +@item With file extension taken from the specified path. Daemon is run + with multiple URLs specified. + +@example +$ paster some-other-image.webp +http://paster.example.com/O6D2O3N5HPH63ZFIYF4A.webp +https://paster.example.com/O6D2O3N5HPH63ZFIYF4A.webp +ftp://paster.example.com/pub/pastes/O6D2O3N5HPH63ZFIYF4A.webp +SHA512/2: 2ffe10846ec637d29ab9145b98c3699653c01910bb6d9e00e41f7fe02c5882a8 +@end example + +@item +@example +$ grep whatever ... | paster +$ import png:- | paster png +$ import -define webp:lossless=true webp:- | paster webp +$ echo http://example.com | paster url +$ paster < /proc/cpuinfo +@end example + +@item Pasting the @url{https://asciinema.org/, asciicast} requires +@file{.cast} extension. @file{.cast.html} URLs will appear. + +@example +$ paster path/to/ascii.cast +http://paster.example.com/ST4LOKGUISMACAAFC4CA.cast +SHA512/2: 171e39f35b58b39f0bc2f3def59955d6573756374584d5443afa16d31032fdf3 +http://paster.example.com/ST4LOKGUISMACAAFC4CA.cast.html +@end example + +@end itemize diff --git a/doc/features.texi b/doc/features.texi new file mode 100644 index 0000000..56bcfa6 --- /dev/null +++ b/doc/features.texi @@ -0,0 +1,31 @@ +@node Features +@unnumbered Features + +@itemize + +@item It uses file system for storing the pastes + +@item Pastes are shared through the external program (HTTP, FTP, Gopher, ...) + +@item Paste files have an extension (@file{.txt} by default), that can + be overriden for the given paste. So your HTTP service can answer + with varying @code{Content-Types}. You can share images for example, + not only plaintext + +@item No excessive HTTP protocol: just send + @url{https://en.wikipedia.org/wiki/Bencode, bencode}-ed dictionary + with the data over the TCP + +@item Newline is appended for @file{.txt}/@file{.url} pastes, if it is missing + +@item SHA512/2 checksum is sent back to you, for integrity checking + +@item Intended to be run as a @url{https://cr.yp.to/ucspi-tcp.html, UCSPI-TCP} + service @url{http://cr.yp.to/daemontools.html, daemontools}-like supervisor + +@item Can automatically generate HTML files with the links for automatic + @url{https://asciinema.org/, asciicasts} playback. + +@item You can clear an old ones with simple: + @code{find pastes -ctime XXX -delete} +@end itemize diff --git a/doc/index.texi b/doc/index.texi new file mode 100644 index 0000000..03d3e0f --- /dev/null +++ b/doc/index.texi @@ -0,0 +1,30 @@ +\input texinfo +@documentencoding UTF-8 +@settitle paster + +@copying +Copyright @copyright{} 2021-2022 @email{stargrave@@stargrave.org, Sergey Matveev} +@end copying + +@node Top +@top paster + +Are you tired of too complicated solutions even for the simple task like +paste storage? I too. That is why that @strong{paster daemon} is here. + +paster is +@url{https://www.gnu.org/philosophy/pragmatic.html, copylefted} +@url{https://www.gnu.org/philosophy/free-sw.html, free software} +licenced under @url{https://www.gnu.org/licenses/gpl-3.0.html, GNU GPLv3}. + +Please send questions, bug reports and patches to @url{paster@@stargrave.org}. + +@insertcopying + +@include features.texi +@include examples.texi +@include install.texi +@include asciicast.texi +@include protocol.texi + +@bye diff --git a/doc/install.texi b/doc/install.texi new file mode 100644 index 0000000..8083cb3 --- /dev/null +++ b/doc/install.texi @@ -0,0 +1,104 @@ +@node Install +@unnumbered Install + +@itemize + +@item +Install paster itself: + +@example +$ go get go.stargrave.org/paster +@end example + +If you have got problems with your trust anchors, unwilling to +authenticate @code{go.stargrave.org}'s TLS connection, then clone the +repository from @url{git://git.stargrave.org/paster.git} and build it +as ordinary Go package with @code{go build}. + +@item +Add @code{paster} user and @code{pastes} directory, also accessible by +HTTP service (@url{http://www.godlighty.stargrave.org/, @code{godlighty}} +user in current example): + +@example +# pw useradd paster -s /usr/sbin/nologin -w no -d /path/to/pastes +# mkdir /path/to/pastes +# cat > /path/to/pastes/index.html < + + paster + Paste service. + +EOF +# chown -R paster:godlighty pastes +# chmod 2750 pastes +# chmod 640 /path/to/pastes/index.html +@end example + +@item +Create @url{http://cr.yp.to/daemontools.html, daemontools} + +@url{https://cr.yp.to/ucspi-tcp.html, UCSPI-TCP} service: + +@example +# mkdir -p /var/service/.paster/log/main + +# cat > /var/service/.paster/run <&1 +EOF + +# cat > /var/service/.paster/log/run < $tmpl <&1 +@end example + +@item +Be sure that your HTTP/whatever server uses proper @code{Content-Type} +based on filename's extension (@code{text/plain} for @file{.txt}, +@code{image/jxl} for @file{.jxl} and so on). + +@end itemize diff --git a/doc/protocol.texi b/doc/protocol.texi new file mode 100644 index 0000000..12e0a4f --- /dev/null +++ b/doc/protocol.texi @@ -0,0 +1,16 @@ +@node Protocol +@unnumbered Protocol + +Protocol is very simple: @url{https://en.wikipedia.org/wiki/Bencode, +bencode}d dictionary is sent over TCP. + +@itemize +@item @code{v} key contains the data you want to paste +@item optional @code{e} key, holding the desired filename extension, + without the leading dot, up to 9 characters long +@end itemize + +@example +"hello world" => d1:v11:hello worlde +"http://example.com/" and "url" extension => d1:e3:url1:v18:http://example.come +@end example diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 0000000..44fa2e0 --- /dev/null +++ b/doc/style.css @@ -0,0 +1,5 @@ +body { background-color: #AEBECE } +h1, h2, h3, h4 { text-align: center } +h1, h2, h3, h4, strong { color: #900090 } +pre { background-color: #CCCCCC } +table, th, td { border: 1px solid black ; border-collapse: collapse } diff --git a/doc/www.do b/doc/www.do new file mode 100644 index 0000000..ea98526 --- /dev/null +++ b/doc/www.do @@ -0,0 +1,15 @@ +redo-ifchange *.texi +html=paster.html +rm -f $html/*.html +${MAKEINFO:=makeinfo} --html \ + --css-include style.css \ + --set-customization-variable SECTION_NAME_IN_TITLE=1 \ + --set-customization-variable TREE_TRANSFORMATIONS=complete_tree_nodes_menus \ + --set-customization-variable FORMAT_MENU=menu \ + --set-customization-variable SHOW_TITLE=0 \ + --set-customization-variable DATE_IN_HEADER=1 \ + --set-customization-variable CLOSE_QUOTE_SYMBOL=\" \ + --set-customization-variable OPEN_QUOTE_SYMBOL=\" \ + -o $html index.texi +find $html -type d -exec chmod 755 {} + +find $html -type f -exec chmod 644 {} + diff --git a/main.go b/main.go index 139b536..89bcc6e 100644 --- a/main.go +++ b/main.go @@ -22,22 +22,57 @@ import ( "bytes" "crypto/rand" "crypto/sha512" + _ "embed" "encoding/base32" "encoding/hex" "flag" "fmt" + "html/template" "io" "os" "strconv" ) +var ( + //go:embed asciicast.tmpl + ASCIICastHTMLTmplRaw string + ASCIICastHTMLTmpl = template.Must(template.New("asciicast").Parse( + ASCIICastHTMLTmplRaw, + )) +) + func fatal(s string) { fmt.Println(s) os.Exit(1) } +func asciicastHTML(playerPath, cast string) error { + var buf bytes.Buffer + err := ASCIICastHTMLTmpl.Execute(&buf, struct { + PlayerPath string + Cast string + }{ + PlayerPath: playerPath, + Cast: cast, + }) + if err != nil { + return err + } + fn := cast + ".html" + fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, os.FileMode(0666)) + if err != nil { + return err + } + if _, err = fd.Write(buf.Bytes()); err != nil { + os.Remove(fn) + return err + } + return fd.Close() +} + func main() { maxSize := flag.Uint64("max-size", 1<<20, "Maximal upload size") + asciicastPath := flag.String("asciicast-path", "", "Generate HTMLs for .cast asciicasts, specify \"asciinema-player-v2.6.1\"") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: paster [options] URL [...]\n") flag.PrintDefaults() @@ -150,7 +185,15 @@ AnotherKey: for _, u := range flag.Args() { fmt.Println(u + fn[1:]) } - fmt.Println(hex.EncodeToString(h.Sum(nil)[:512/2/8])) + fmt.Println("SHA512/2:", hex.EncodeToString(h.Sum(nil)[:512/2/8])) + if ext == ".cast" && *asciicastPath != "" { + if err = asciicastHTML(*asciicastPath, fn[1:]); err != nil { + goto Failed + } + for _, u := range flag.Args() { + fmt.Println(u + fn[1:] + ".html") + } + } fmt.Fprintf( os.Stderr, "[%s]:%s %s %d\n", -- 2.44.0