github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/cmd/swarm/upload.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Command bzzup uploads files to the swarm HTTP API. 18 package main 19 20 import ( 21 "errors" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "mime" 26 "net/http" 27 "os" 28 "os/user" 29 "path" 30 "path/filepath" 31 "strings" 32 33 "github.com/FusionFoundation/efsn/cmd/utils" 34 swarm "github.com/FusionFoundation/efsn/swarm/api/client" 35 "gopkg.in/urfave/cli.v1" 36 ) 37 38 func upload(ctx *cli.Context) { 39 40 args := ctx.Args() 41 var ( 42 bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 43 recursive = ctx.GlobalBool(SwarmRecursiveFlag.Name) 44 wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) 45 defaultPath = ctx.GlobalString(SwarmUploadDefaultPath.Name) 46 fromStdin = ctx.GlobalBool(SwarmUpFromStdinFlag.Name) 47 mimeType = ctx.GlobalString(SwarmUploadMimeType.Name) 48 client = swarm.NewClient(bzzapi) 49 toEncrypt = ctx.Bool(SwarmEncryptedFlag.Name) 50 file string 51 ) 52 53 if len(args) != 1 { 54 if fromStdin { 55 tmp, err := ioutil.TempFile("", "swarm-stdin") 56 if err != nil { 57 utils.Fatalf("error create tempfile: %s", err) 58 } 59 defer os.Remove(tmp.Name()) 60 n, err := io.Copy(tmp, os.Stdin) 61 if err != nil { 62 utils.Fatalf("error copying stdin to tempfile: %s", err) 63 } else if n == 0 { 64 utils.Fatalf("error reading from stdin: zero length") 65 } 66 file = tmp.Name() 67 } else { 68 utils.Fatalf("Need filename as the first and only argument") 69 } 70 } else { 71 file = expandPath(args[0]) 72 } 73 74 if !wantManifest { 75 f, err := swarm.Open(file) 76 if err != nil { 77 utils.Fatalf("Error opening file: %s", err) 78 } 79 defer f.Close() 80 hash, err := client.UploadRaw(f, f.Size, toEncrypt) 81 if err != nil { 82 utils.Fatalf("Upload failed: %s", err) 83 } 84 fmt.Println(hash) 85 return 86 } 87 88 stat, err := os.Stat(file) 89 if err != nil { 90 utils.Fatalf("Error opening file: %s", err) 91 } 92 93 // define a function which either uploads a directory or single file 94 // based on the type of the file being uploaded 95 var doUpload func() (hash string, err error) 96 if stat.IsDir() { 97 doUpload = func() (string, error) { 98 if !recursive { 99 return "", errors.New("Argument is a directory and recursive upload is disabled") 100 } 101 if defaultPath != "" { 102 // construct absolute default path 103 absDefaultPath, _ := filepath.Abs(defaultPath) 104 absFile, _ := filepath.Abs(file) 105 // make sure absolute directory ends with only one "/" 106 // to trim it from absolute default path and get relative default path 107 absFile = strings.TrimRight(absFile, "/") + "/" 108 if absDefaultPath != "" && absFile != "" && strings.HasPrefix(absDefaultPath, absFile) { 109 defaultPath = strings.TrimPrefix(absDefaultPath, absFile) 110 } 111 } 112 return client.UploadDirectory(file, defaultPath, "", toEncrypt) 113 } 114 } else { 115 doUpload = func() (string, error) { 116 f, err := swarm.Open(file) 117 if err != nil { 118 return "", fmt.Errorf("error opening file: %s", err) 119 } 120 defer f.Close() 121 if mimeType == "" { 122 mimeType = detectMimeType(file) 123 } 124 f.ContentType = mimeType 125 return client.Upload(f, "", toEncrypt) 126 } 127 } 128 hash, err := doUpload() 129 if err != nil { 130 utils.Fatalf("Upload failed: %s", err) 131 } 132 fmt.Println(hash) 133 } 134 135 // Expands a file path 136 // 1. replace tilde with users home dir 137 // 2. expands embedded environment variables 138 // 3. cleans the path, e.g. /a/b/../c -> /a/c 139 // Note, it has limitations, e.g. ~someuser/tmp will not be expanded 140 func expandPath(p string) string { 141 if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 142 if home := homeDir(); home != "" { 143 p = home + p[1:] 144 } 145 } 146 return path.Clean(os.ExpandEnv(p)) 147 } 148 149 func homeDir() string { 150 if home := os.Getenv("HOME"); home != "" { 151 return home 152 } 153 if usr, err := user.Current(); err == nil { 154 return usr.HomeDir 155 } 156 return "" 157 } 158 159 func detectMimeType(file string) string { 160 if ext := filepath.Ext(file); ext != "" { 161 return mime.TypeByExtension(ext) 162 } 163 f, err := os.Open(file) 164 if err != nil { 165 return "" 166 } 167 defer f.Close() 168 buf := make([]byte, 512) 169 if n, _ := f.Read(buf); n > 0 { 170 return http.DetectContentType(buf) 171 } 172 return "" 173 }