mirror of https://github.com/emojisum/emojisum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
4.2 KiB
186 lines
4.2 KiB
package main |
|
|
|
import ( |
|
"bufio" |
|
"crypto/sha1" |
|
"encoding/hex" |
|
"errors" |
|
"flag" |
|
"fmt" |
|
"io" |
|
"os" |
|
"strings" |
|
|
|
esum "github.com/emojisum/emojisum/emoji" |
|
"github.com/kyokomi/emoji" |
|
) |
|
|
|
func main() { |
|
if err := run(); err != nil { |
|
fmt.Fprintln(os.Stderr, err) |
|
os.Exit(1) |
|
} |
|
} |
|
|
|
var ( |
|
flParseOpenSSL = flag.Bool("pb", false, "parse the output of BSD/OpenSSL style checksums on stdin (`openssl sha256 ./foo | emojisum -pb`)") |
|
flParseCoreUtils = flag.Bool("pg", false, "parse the output of GNU/CoreUtils style checksums on stdin (`sha256sum ./foo | emojisum -pg`)") |
|
) |
|
|
|
func run() error { |
|
flag.Parse() |
|
|
|
if *flParseOpenSSL { |
|
buf := bufio.NewReader(os.Stdin) |
|
for { |
|
line, err := buf.ReadString('\n') |
|
if err != nil && err == io.EOF { |
|
return nil |
|
} else if err != nil { |
|
return err |
|
} |
|
hash, name, sum, err := parseOpenSSL(line) |
|
if err != nil { |
|
fmt.Fprintf(os.Stderr, "%s: %q\n", err, line) |
|
continue |
|
} |
|
str := emojiFromBytes(sum) |
|
fmt.Printf("%s(%s)= %x\n", hash, name, sum) |
|
fmt.Printf("%s(%s)= %s\n", hash, name, str) |
|
fmt.Printf("%s(%s)= ", hash, name) |
|
emoji.Println(str) |
|
} |
|
// never gets here because of the return on EOF or err |
|
} |
|
if *flParseCoreUtils { |
|
buf := bufio.NewReader(os.Stdin) |
|
for { |
|
line, err := buf.ReadString('\n') |
|
if err != nil && err == io.EOF { |
|
return nil |
|
} else if err != nil { |
|
return err |
|
} |
|
name, sum, err := parseCoreUtils(line) |
|
if err != nil { |
|
fmt.Fprintf(os.Stderr, "%s: %q\n", err, line) |
|
continue |
|
} |
|
str := emojiFromBytes(sum) |
|
fmt.Printf("%x %s\n", sum, name) |
|
fmt.Printf("%s %s\n", str, name) |
|
emoji.Print(str) |
|
fmt.Printf(" %s\n", name) |
|
} |
|
// never gets here because of the return on EOF or err |
|
} |
|
|
|
// Otherwise do the checksum ourselves |
|
|
|
if flag.NArg() == 0 { |
|
sum, err := Sum(os.Stdin) |
|
if err != nil { |
|
return err |
|
} |
|
str := emojiFromBytes(sum) |
|
fmt.Printf("SHA1(-)= %x\n", sum) |
|
fmt.Printf("SHA1(-)= %s\n", str) |
|
fmt.Printf("SHA1(-)= ") |
|
emoji.Println(str) |
|
return nil |
|
} |
|
|
|
for _, arg := range flag.Args() { |
|
fh, err := os.Open(arg) |
|
if err != nil { |
|
return err |
|
} |
|
defer fh.Close() |
|
|
|
sum, err := Sum(fh) |
|
if err != nil { |
|
return err |
|
} |
|
str := emojiFromBytes(sum) |
|
fmt.Printf("SHA1(%s)= %x\n", arg, sum) |
|
fmt.Printf("SHA1(%s)= %s\n", arg, str) |
|
fmt.Printf("SHA1(%s)= ", arg) |
|
emoji.Println(str) |
|
} |
|
return nil |
|
} |
|
|
|
/* |
|
openssl sum: |
|
``` |
|
$> openssl sha256 tmp.efLuko |
|
SHA256(tmp.efLuko)= f18bd8b680e834ab8097a66deb0255821195d9624e39da6b65903ff6a09a01bb |
|
``` |
|
*/ |
|
func parseOpenSSL(line string) (hash, filename string, sum []byte, err error) { |
|
if !strings.Contains(line, "(") { |
|
return "", "", nil, ErrNotOpenSSLLine |
|
} |
|
chunks := strings.SplitN(strings.TrimRight(line, "\n"), ")= ", 2) |
|
if len(chunks) != 2 { |
|
return "", "", nil, ErrNotOpenSSLLine |
|
} |
|
chunksprime := strings.SplitN(chunks[0], "(", 2) |
|
if len(chunks) != 2 { |
|
return "", "", nil, ErrNotOpenSSLLine |
|
} |
|
sum, err = hex.DecodeString(chunks[1]) |
|
if err != nil { |
|
return "", "", nil, err |
|
} |
|
return chunksprime[0], chunksprime[1], sum, nil |
|
} |
|
|
|
// ErrNotOpenSSLLine when the line to parse is not formated like an OpenSSL checksum line |
|
var ErrNotOpenSSLLine = errors.New("not an openssl checksum line") |
|
|
|
/* |
|
coreutils output: |
|
``` |
|
$ sha256sum ./tmp.efLuko |
|
f18bd8b680e834ab8097a66deb0255821195d9624e39da6b65903ff6a09a01bb ./tmp.efLuko |
|
``` |
|
*/ |
|
func parseCoreUtils(line string) (filename string, sum []byte, err error) { |
|
chunks := strings.SplitN(strings.TrimRight(line, "\n"), " ", 2) |
|
if len(chunks) != 2 { |
|
return "", nil, ErrNotCoreUtilsLine |
|
} |
|
sum, err = hex.DecodeString(chunks[0]) |
|
if err != nil { |
|
return "", nil, err |
|
} |
|
return chunks[1], sum, nil |
|
} |
|
|
|
// ErrNotCoreUtilsLine when the line to parse is not formated like a coreutils checksum line |
|
var ErrNotCoreUtilsLine = errors.New("not a coreutils checksum line") |
|
|
|
// Sum is a basic wrapper around crypto/sha1 |
|
func Sum(r io.Reader) ([]byte, error) { |
|
h := sha1.New() |
|
if _, err := io.Copy(h, r); err != nil { |
|
return nil, err |
|
} |
|
sum := h.Sum(nil) |
|
return sum[:], nil |
|
} |
|
|
|
func emojiFromBytes(buf []byte) string { |
|
var ret string |
|
for _, b := range buf { |
|
for _, e := range esum.Map(b) { |
|
// use the first colon notation word and continue |
|
if esum.IsColonNotation(e) { |
|
ret = ret + e |
|
break |
|
} |
|
} |
|
} |
|
return ret |
|
}
|
|
|