2016-12-02 16:32:31 +00:00
package main
import (
"bufio"
"crypto/sha1"
"encoding/hex"
"errors"
"flag"
"fmt"
"io"
"os"
"strings"
"github.com/kyokomi/emoji"
)
func main ( ) {
if err := run ( ) ; err != nil {
fmt . Fprintln ( os . Stderr , err )
os . Exit ( 1 )
}
}
var (
flParseOpenSSL = flag . Bool ( "parse-openssl" , false , "parse the output of OpenSSL style checksums on stdin (`openssl sha256 ./foo | emojisum -parse-openssl`)" )
flParseCoreUtils = flag . Bool ( "parse-coreutils" , false , "parse the output of CoreUtils style checksums on stdin (`sha256sum ./foo | emojisum -parse-coreutils`)" )
)
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 )
}
2016-12-13 18:18:58 +00:00
// never gets here because of the return on EOF or err
2016-12-02 16:32:31 +00:00
}
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 )
}
2016-12-13 18:18:58 +00:00
// never gets here because of the return on EOF or err
2016-12-02 16:32:31 +00:00
}
// Otherwise do the checksum ourselves
if flag . NArg ( ) == 0 {
sum , err := Sum ( os . Stdin )
if err != nil {
return err
}
str := emojiFromBytes ( sum )
2016-12-02 18:05:45 +00:00
fmt . Printf ( "SHA1(-)= %x\n" , sum )
fmt . Printf ( "SHA1(-)= %s\n" , str )
fmt . Printf ( "SHA1(-)= " )
2016-12-02 16:32:31 +00:00
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 )
2016-12-02 18:05:45 +00:00
fmt . Printf ( "SHA1(%s)= %x\n" , arg , sum )
fmt . Printf ( "SHA1(%s)= %s\n" , arg , str )
fmt . Printf ( "SHA1(%s)= " , arg )
2016-12-02 16:32:31 +00:00
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
}
2016-12-13 18:18:58 +00:00
// ErrNotOpenSSLLine when the line to parse is not formated like an OpenSSL checksum line
2016-12-02 16:32:31 +00:00
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
}
2016-12-13 18:18:58 +00:00
// ErrNotCoreUtilsLine when the line to parse is not formated like a coreutils checksum line
2016-12-02 16:32:31 +00:00
var ErrNotCoreUtilsLine = errors . New ( "not a coreutils checksum line" )
2016-12-13 18:18:58 +00:00
// Sum is a basic wrapper around crypto/sha1
2016-12-02 16:32:31 +00:00
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 {
ret = ret + emojiFromRune ( b )
}
return ret
}
func emojiFromRune ( b byte ) string {
//fmt.Printf("%#v\n", b)
return emojiMap [ int ( b ) ]
}
// these are an ordered list, referened by a byte (each byte of a checksum digest)
var emojiMap = [ ] string {
":+1:" ,
":8ball:" ,
":airplane:" ,
":alien:" ,
":anchor:" ,
":angel:" ,
":angry:" ,
":ant:" ,
":apple:" ,
":art:" ,
":baby:" ,
":baby_bottle:" ,
":back:" ,
":bamboo:" ,
":banana:" ,
":barber:" ,
":bathtub:" ,
":beer:" ,
":bell:" ,
":bicyclist:" ,
":bird:" ,
":birthday:" ,
":blossom:" ,
":blue_car:" ,
":boar:" ,
":bomb:" ,
":boom:" ,
":bow:" ,
":boy:" ,
":broken_heart:" ,
":bulb:" ,
":bus:" ,
":cactus:" ,
":calendar:" ,
":camera:" ,
":candy:" ,
":cat:" ,
":cherries:" ,
":children_crossing:" ,
":chocolate_bar:" ,
":clap:" ,
":cloud:" ,
":clubs:" ,
":cn:" ,
":coffee:" ,
":construction:" ,
":cookie:" ,
":copyright:" ,
":corn:" ,
":cow:" ,
":crescent_moon:" ,
":crown:" ,
":cry:" ,
":crystal_ball:" ,
":curly_loop:" ,
":dancers:" ,
":dash:" ,
":de:" ,
":diamonds:" ,
":dog:" ,
":doughnut:" ,
":dragon:" ,
":dvd:" ,
":ear:" ,
":eggplant:" ,
":elephant:" ,
":end:" ,
":envelope:" ,
":es:" ,
":eyes:" ,
":facepunch:" ,
":family:" ,
":ferris_wheel:" ,
":finnadie:" ,
":fire:" ,
":fireworks:" ,
":floppy_disk:" ,
":football:" ,
":fork_and_knife:" ,
":four_leaf_clover:" ,
":fr:" ,
":fries:" ,
":frog:" ,
":fu:" ,
":full_moon:" ,
":game_die:" ,
2016-12-03 15:10:35 +00:00
":eu:" ,
2016-12-02 16:32:31 +00:00
":gem:" ,
":girl:" ,
":goat:" ,
":grimacing:" ,
":grin:" ,
":guardsman:" ,
":guitar:" ,
":gun:" ,
":hamburger:" ,
":hammer:" ,
":hamster:" ,
":hear_no_evil:" ,
":heart:" ,
":heart_eyes_cat:" ,
":hearts:" ,
":heavy_check_mark:" ,
":moyai:" ,
":izakaya_lantern:" ,
":helicopter:" ,
":hocho:" ,
":honeybee:" ,
":horse:" ,
":horse_racing:" ,
":hourglass:" ,
":house:" ,
":hurtrealbad:" ,
":icecream:" ,
":imp:" ,
":it:" ,
":jack_o_lantern:" ,
":japanese_goblin:" ,
":jp:" ,
":key:" ,
":kiss:" ,
":kissing_cat:" ,
":koala:" ,
":kr:" ,
":lemon:" ,
":lipstick:" ,
":lock:" ,
":lollipop:" ,
":man:" ,
":maple_leaf:" ,
":mask:" ,
":metal:" ,
":microscope:" ,
":moneybag:" ,
":monkey:" ,
":mount_fuji:" ,
":muscle:" ,
":mushroom:" ,
":musical_keyboard:" ,
":musical_score:" ,
":nail_care:" ,
":new_moon:" ,
":no_entry:" ,
":nose:" ,
":notes:" ,
":nut_and_bolt:" ,
":o:" ,
":ocean:" ,
":ok_hand:" ,
":on:" ,
":package:" ,
":palm_tree:" ,
":panda_face:" ,
":paperclip:" ,
":partly_sunny:" ,
":passport_control:" ,
":paw_prints:" ,
":peach:" ,
":penguin:" ,
":phone:" ,
":pig:" ,
":pill:" ,
":pineapple:" ,
":pizza:" ,
":point_left:" ,
":point_right:" ,
":poop:" ,
":poultry_leg:" ,
":pray:" ,
":princess:" ,
":purse:" ,
":pushpin:" ,
":rabbit:" ,
":rainbow:" ,
":raised_hand:" ,
":recycle:" ,
":red_car:" ,
":registered:" ,
":ribbon:" ,
":rice:" ,
":rocket:" ,
":roller_coaster:" ,
":rooster:" ,
":ru:" ,
":sailboat:" ,
":santa:" ,
":satellite:" ,
":satisfied:" ,
":saxophone:" ,
":scissors:" ,
":see_no_evil:" ,
":sheep:" ,
":shell:" ,
":shoe:" ,
":ski:" ,
":skull:" ,
":sleepy:" ,
":smile:" ,
":smiley_cat:" ,
":smirk:" ,
":smoking:" ,
":snail:" ,
":snake:" ,
":snowflake:" ,
":soccer:" ,
":soon:" ,
":space_invader:" ,
":spades:" ,
":speak_no_evil:" ,
":star:" ,
":stars:" ,
":statue_of_liberty:" ,
":steam_locomotive:" ,
":sunflower:" ,
":sunglasses:" ,
":sunny:" ,
":sunrise:" ,
":surfer:" ,
":swimmer:" ,
":syringe:" ,
":tada:" ,
":tangerine:" ,
":taxi:" ,
":tennis:" ,
":tent:" ,
":thought_balloon:" ,
":tm:" ,
":toilet:" ,
":tongue:" ,
":tophat:" ,
":tractor:" ,
":trolleybus:" ,
":trollface:" ,
":trophy:" ,
":trumpet:" ,
":turtle:" ,
":two_men_holding_hands:" ,
":two_women_holding_hands:" ,
":uk:" ,
":umbrella:" ,
":unlock:" ,
":us:" ,
":v:" ,
":vhs:" ,
":violin:" ,
":warning:" ,
":watermelon:" ,
":wave:" ,
":wavy_dash:" ,
":wc:" ,
":wheelchair:" ,
":woman:" ,
":x:" ,
":yum:" ,
":zap:" ,
":zzz:" ,
}