Browse Source

implements log option (#171)

* implements log option
tags/v1.0.0
Andrea Spacca 5 years ago
committed by GitHub
parent
commit
6982590cb0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 51 deletions
  1. +4
    -0
      README.md
  2. +13
    -4
      cmd/cmd.go
  3. +1
    -1
      server/clamav.go
  4. +22
    -14
      server/server.go
  5. +32
    -29
      server/storage.go
  6. +2
    -3
      server/virustotal.go

+ 4
- 0
README.md View File

@@ -170,6 +170,10 @@ Contributions are welcome.


**Uvis Grinfelds** **Uvis Grinfelds**


## Maintainer

**Andrea Spacca**

## Copyright and license ## Copyright and license


Code and documentation copyright 2011-2018 Remco Verhoef. Code and documentation copyright 2011-2018 Remco Verhoef.


+ 13
- 4
cmd/cmd.go View File

@@ -10,6 +10,7 @@ import (
"github.com/dutchcoders/transfer.sh/server" "github.com/dutchcoders/transfer.sh/server"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/minio/cli" "github.com/minio/cli"
"log"
) )


var Version = "0.1" var Version = "0.1"
@@ -184,6 +185,8 @@ func VersionAction(c *cli.Context) {
} }


func New() *Cmd { func New() *Cmd {
logger := log.New(os.Stdout, "[transfer.sh]", log.LstdFlags)

app := cli.NewApp() app := cli.NewApp()
app.Name = "transfer.sh" app.Name = "transfer.sh"
app.Author = "" app.Author = ""
@@ -235,6 +238,12 @@ func New() *Cmd {
options = append(options, server.TempPath(v)) options = append(options, server.TempPath(v))
} }


if v := c.String("log"); v != "" {
options = append(options, server.LogFile(logger, v))
} else {
options = append(options, server.Logger(logger))
}

if v := c.String("lets-encrypt-hosts"); v != "" { if v := c.String("lets-encrypt-hosts"); v != "" {
options = append(options, server.UseLetsEncrypt(strings.Split(v, ","))) options = append(options, server.UseLetsEncrypt(strings.Split(v, ",")))
} }
@@ -279,7 +288,7 @@ func New() *Cmd {
panic("secret-key not set.") panic("secret-key not set.")
} else if bucket := c.String("bucket"); bucket == "" { } else if bucket := c.String("bucket"); bucket == "" {
panic("bucket not set.") panic("bucket not set.")
} else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, c.String("s3-endpoint")); err != nil {
} else if storage, err := server.NewS3Storage(accessKey, secretKey, bucket, c.String("s3-endpoint"), logger); err != nil {
panic(err) panic(err)
} else { } else {
options = append(options, server.UseStorage(storage)) options = append(options, server.UseStorage(storage))
@@ -291,7 +300,7 @@ func New() *Cmd {
panic("local-config-path not set.") panic("local-config-path not set.")
} else if basedir := c.String("basedir"); basedir == "" { } else if basedir := c.String("basedir"); basedir == "" {
panic("basedir not set.") panic("basedir not set.")
} else if storage, err := server.NewGDriveStorage(clientJsonFilepath, localConfigPath, basedir); err != nil {
} else if storage, err := server.NewGDriveStorage(clientJsonFilepath, localConfigPath, basedir, logger); err != nil {
panic(err) panic(err)
} else { } else {
options = append(options, server.UseStorage(storage)) options = append(options, server.UseStorage(storage))
@@ -299,7 +308,7 @@ func New() *Cmd {
case "local": case "local":
if v := c.String("basedir"); v == "" { if v := c.String("basedir"); v == "" {
panic("basedir not set.") panic("basedir not set.")
} else if storage, err := server.NewLocalStorage(v); err != nil {
} else if storage, err := server.NewLocalStorage(v, logger); err != nil {
panic(err) panic(err)
} else { } else {
options = append(options, server.UseStorage(storage)) options = append(options, server.UseStorage(storage))
@@ -313,7 +322,7 @@ func New() *Cmd {
) )


if err != nil { if err != nil {
fmt.Println(color.RedString("Error starting server: %s", err.Error()))
logger.Println(color.RedString("Error starting server: %s", err.Error()))
return return
} }




+ 1
- 1
server/clamav.go View File

@@ -47,7 +47,7 @@ func (s *Server) scanHandler(w http.ResponseWriter, r *http.Request) {
contentLength := r.ContentLength contentLength := r.ContentLength
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")


log.Printf("Scanning %s %d %s", filename, contentLength, contentType)
s.logger.Printf("Scanning %s %d %s", filename, contentLength, contentType)


var reader io.Reader var reader io.Reader




+ 22
- 14
server/server.go View File

@@ -26,7 +26,6 @@ package server


import ( import (
"errors" "errors"
"fmt"
"log" "log"
"math/rand" "math/rand"
"mime" "mime"
@@ -129,14 +128,21 @@ func TempPath(s string) OptionFn {
} }
} }


func LogFile(s string) OptionFn {
func LogFile(logger *log.Logger, s string) OptionFn {
return func(srvr *Server) { return func(srvr *Server) {
f, err := os.OpenFile(s, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) f, err := os.OpenFile(s, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil { if err != nil {
log.Fatalf("error opening file: %v", err) log.Fatalf("error opening file: %v", err)
} }


log.SetOutput(f)
logger.SetOutput(f)
srvr.logger = logger
}
}

func Logger(logger *log.Logger) OptionFn {
return func(srvr *Server) {
srvr.logger = logger
} }
} }


@@ -214,6 +220,8 @@ type Server struct {
AuthUser string AuthUser string
AuthPass string AuthPass string


logger *log.Logger

tlsConfig *tls.Config tlsConfig *tls.Config


profilerEnabled bool profilerEnabled bool
@@ -269,7 +277,7 @@ func (s *Server) Run() {
listening = true listening = true


go func() { go func() {
fmt.Println("Profiled listening at: :6060")
s.logger.Println("Profiled listening at: :6060")


http.ListenAndServe(":6060", nil) http.ListenAndServe(":6060", nil)
}() }()
@@ -280,7 +288,7 @@ func (s *Server) Run() {
var fs http.FileSystem var fs http.FileSystem


if s.webPath != "" { if s.webPath != "" {
log.Println("Using static file path: ", s.webPath)
s.logger.Println("Using static file path: ", s.webPath)


fs = http.Dir(s.webPath) fs = http.Dir(s.webPath)


@@ -299,7 +307,7 @@ func (s *Server) Run() {
for _, path := range web.AssetNames() { for _, path := range web.AssetNames() {
bytes, err := web.Asset(path) bytes, err := web.Asset(path)
if err != nil { if err != nil {
log.Panicf("Unable to parse: path=%s, err=%s", path, err)
s.logger.Panicf("Unable to parse: path=%s, err=%s", path, err)
} }


htmlTemplates.New(stripPrefix(path)).Parse(string(bytes)) htmlTemplates.New(stripPrefix(path)).Parse(string(bytes))
@@ -341,7 +349,7 @@ func (s *Server) Run() {


u, err := url.Parse(r.Referer()) u, err := url.Parse(r.Referer())
if err != nil { if err != nil {
log.Fatal(err)
s.logger.Fatal(err)
return return
} }


@@ -371,9 +379,9 @@ func (s *Server) Run() {


mime.AddExtensionType(".md", "text/x-markdown") mime.AddExtensionType(".md", "text/x-markdown")


log.Printf("Transfer.sh server started.\nusing temp folder: %s\nusing storage provider: %s", s.tempPath, s.storage.Type())
s.logger.Printf("Transfer.sh server started.\nusing temp folder: %s\nusing storage provider: %s", s.tempPath, s.storage.Type())


h := handlers.PanicHandler(handlers.LogHandler(LoveHandler(s.RedirectHandler(r)), handlers.NewLogOptions(log.Printf, "_default_")), nil)
h := handlers.PanicHandler(handlers.LogHandler(LoveHandler(s.RedirectHandler(r)), handlers.NewLogOptions(s.logger.Printf, "_default_")), nil)


if !s.TLSListenerOnly { if !s.TLSListenerOnly {
srvr := &http.Server{ srvr := &http.Server{
@@ -382,7 +390,7 @@ func (s *Server) Run() {
} }


listening = true listening = true
log.Printf("listening on port: %v\n", s.ListenerString)
s.logger.Printf("listening on port: %v\n", s.ListenerString)


go func() { go func() {
srvr.ListenAndServe() srvr.ListenAndServe()
@@ -391,7 +399,7 @@ func (s *Server) Run() {


if s.TLSListenerString != "" { if s.TLSListenerString != "" {
listening = true listening = true
log.Printf("listening on port: %v\n", s.TLSListenerString)
s.logger.Printf("listening on port: %v\n", s.TLSListenerString)


go func() { go func() {
s := &http.Server{ s := &http.Server{
@@ -406,7 +414,7 @@ func (s *Server) Run() {
}() }()
} }


log.Printf("---------------------------")
s.logger.Printf("---------------------------")


term := make(chan os.Signal, 1) term := make(chan os.Signal, 1)
signal.Notify(term, os.Interrupt) signal.Notify(term, os.Interrupt)
@@ -415,8 +423,8 @@ func (s *Server) Run() {
if listening { if listening {
<-term <-term
} else { } else {
log.Printf("No listener active.")
s.logger.Printf("No listener active.")
} }


log.Printf("Server stopped.")
s.logger.Printf("Server stopped.")
} }

+ 32
- 29
server/storage.go View File

@@ -37,10 +37,11 @@ type Storage interface {
type LocalStorage struct { type LocalStorage struct {
Storage Storage
basedir string basedir string
logger *log.Logger
} }


func NewLocalStorage(basedir string) (*LocalStorage, error) {
return &LocalStorage{basedir: basedir}, nil
func NewLocalStorage(basedir string, logger *log.Logger) (*LocalStorage, error) {
return &LocalStorage{basedir: basedir, logger: logger}, nil
} }


func (s *LocalStorage) Type() string { func (s *LocalStorage) Type() string {
@@ -110,7 +111,6 @@ func (s *LocalStorage) Put(token string, filename string, reader io.Reader, cont
} }


if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil { if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
fmt.Printf("%s", err)
return err return err
} }


@@ -126,15 +126,16 @@ func (s *LocalStorage) Put(token string, filename string, reader io.Reader, cont
type S3Storage struct { type S3Storage struct {
Storage Storage
bucket *s3.Bucket bucket *s3.Bucket
logger *log.Logger
} }


func NewS3Storage(accessKey, secretKey, bucketName, endpoint string) (*S3Storage, error) {
func NewS3Storage(accessKey, secretKey, bucketName, endpoint string, logger *log.Logger) (*S3Storage, error) {
bucket, err := getBucket(accessKey, secretKey, bucketName, endpoint) bucket, err := getBucket(accessKey, secretKey, bucketName, endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
} }


return &S3Storage{bucket: bucket}, nil
return &S3Storage{bucket: bucket, logger: logger}, nil
} }


func (s *S3Storage) Type() string { func (s *S3Storage) Type() string {
@@ -165,7 +166,7 @@ func (s *S3Storage) IsNotExist(err error) bool {
return false return false
} }


log.Printf("IsNotExist: %s, %#v", err.Error(), err)
s.logger.Printf("IsNotExist: %s, %#v", err.Error(), err)


b := (err.Error() == "The specified key does not exist.") b := (err.Error() == "The specified key does not exist.")
b = b || (err.Error() == "Access Denied") b = b || (err.Error() == "Access Denied")
@@ -210,7 +211,7 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content
) )


if multi, err = s.bucket.InitMulti(key, contentType, s3.Private); err != nil { if multi, err = s.bucket.InitMulti(key, contentType, s3.Private); err != nil {
log.Printf(err.Error())
s.logger.Printf(err.Error())
return return
} }


@@ -234,13 +235,13 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content


// Amazon expects parts of at least 5MB, except for the last one // Amazon expects parts of at least 5MB, except for the last one
if count, err = io.ReadAtLeast(reader, buffer, (1<<20)*5); err != nil && err != io.ErrUnexpectedEOF && err != io.EOF { if count, err = io.ReadAtLeast(reader, buffer, (1<<20)*5); err != nil && err != io.ErrUnexpectedEOF && err != io.EOF {
log.Printf(err.Error())
s.logger.Printf(err.Error())
return return
} }


// always send minimal 1 part // always send minimal 1 part
if err == io.EOF && index > 1 { if err == io.EOF && index > 1 {
log.Printf("Waiting for all parts to finish uploading.")
s.logger.Printf("Waiting for all parts to finish uploading.")


// wait for all parts to be finished uploading // wait for all parts to be finished uploading
wg.Wait() wg.Wait()
@@ -257,10 +258,10 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content


// using goroutines because of retries when upload fails // using goroutines because of retries when upload fails
go func(multi *s3.Multi, buffer []byte, index int) { go func(multi *s3.Multi, buffer []byte, index int) {
log.Printf("Uploading part %d %d", index, len(buffer))
s.logger.Printf("Uploading part %d %d", index, len(buffer))


defer func() { defer func() {
log.Printf("Finished part %d %d", index, len(buffer))
s.logger.Printf("Finished part %d %d", index, len(buffer))


wg.Done() wg.Done()


@@ -272,12 +273,12 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content
var part s3.Part var part s3.Part


if part, err = multi.PutPart(index, partReader); err != nil { if part, err = multi.PutPart(index, partReader); err != nil {
log.Printf("Error while uploading part %d %d %s", index, len(buffer), err.Error())
s.logger.Printf("Error while uploading part %d %d %s", index, len(buffer), err.Error())
partsChan <- err partsChan <- err
return return
} }


log.Printf("Finished uploading part %d %d", index, len(buffer))
s.logger.Printf("Finished uploading part %d %d", index, len(buffer))


partsChan <- part partsChan <- part


@@ -294,7 +295,7 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content
parts = append(parts, part.(s3.Part)) parts = append(parts, part.(s3.Part))
case error: case error:
// abort multi upload // abort multi upload
log.Printf("Error during upload, aborting %s.", part.(error).Error())
s.logger.Printf("Error during upload, aborting %s.", part.(error).Error())
err = part.(error) err = part.(error)


multi.Abort() multi.Abort()
@@ -303,14 +304,14 @@ func (s *S3Storage) Put(token string, filename string, reader io.Reader, content


} }


log.Printf("Completing upload %d parts", len(parts))
s.logger.Printf("Completing upload %d parts", len(parts))


if err = multi.Complete(parts); err != nil { if err = multi.Complete(parts); err != nil {
log.Printf("Error during completing upload %d parts %s", len(parts), err.Error())
s.logger.Printf("Error during completing upload %d parts %s", len(parts), err.Error())
return return
} }


log.Printf("Completed uploading %d", len(parts))
s.logger.Printf("Completed uploading %d", len(parts))


return return
} }
@@ -320,9 +321,10 @@ type GDrive struct {
rootId string rootId string
basedir string basedir string
localConfigPath string localConfigPath string
logger *log.Logger
} }


func NewGDriveStorage(clientJsonFilepath string, localConfigPath string, basedir string) (*GDrive, error) {
func NewGDriveStorage(clientJsonFilepath string, localConfigPath string, basedir string, logger *log.Logger) (*GDrive, error) {
b, err := ioutil.ReadFile(clientJsonFilepath) b, err := ioutil.ReadFile(clientJsonFilepath)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -334,12 +336,12 @@ func NewGDriveStorage(clientJsonFilepath string, localConfigPath string, basedir
return nil, err return nil, err
} }


srv, err := drive.New(getGDriveClient(config, localConfigPath))
srv, err := drive.New(getGDriveClient(config, localConfigPath, logger))
if err != nil { if err != nil {
return nil, err return nil, err
} }


storage := &GDrive{service: srv, basedir: basedir, rootId: "", localConfigPath: localConfigPath}
storage := &GDrive{service: srv, basedir: basedir, rootId: "", localConfigPath: localConfigPath, logger: logger}
err = storage.setupRoot() err = storage.setupRoot()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -570,31 +572,31 @@ func (s *GDrive) Put(token string, filename string, reader io.Reader, contentTyp
} }


// Retrieve a token, saves the token, then returns the generated client. // Retrieve a token, saves the token, then returns the generated client.
func getGDriveClient(config *oauth2.Config, localConfigPath string) *http.Client {
func getGDriveClient(config *oauth2.Config, localConfigPath string, logger *log.Logger) *http.Client {
tokenFile := filepath.Join(localConfigPath, GDriveTokenJsonFile) tokenFile := filepath.Join(localConfigPath, GDriveTokenJsonFile)
tok, err := gDriveTokenFromFile(tokenFile) tok, err := gDriveTokenFromFile(tokenFile)
if err != nil { if err != nil {
tok = getGDriveTokenFromWeb(config)
saveGDriveToken(tokenFile, tok)
tok = getGDriveTokenFromWeb(config, logger)
saveGDriveToken(tokenFile, tok, logger)
} }


return config.Client(context.Background(), tok) return config.Client(context.Background(), tok)
} }


// Request a token from the web, then returns the retrieved token. // Request a token from the web, then returns the retrieved token.
func getGDriveTokenFromWeb(config *oauth2.Config) *oauth2.Token {
func getGDriveTokenFromWeb(config *oauth2.Config, logger *log.Logger) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the "+ fmt.Printf("Go to the following link in your browser then type the "+
"authorization code: \n%v\n", authURL) "authorization code: \n%v\n", authURL)


var authCode string var authCode string
if _, err := fmt.Scan(&authCode); err != nil { if _, err := fmt.Scan(&authCode); err != nil {
log.Fatalf("Unable to read authorization code %v", err)
logger.Fatalf("Unable to read authorization code %v", err)
} }


tok, err := config.Exchange(context.TODO(), authCode) tok, err := config.Exchange(context.TODO(), authCode)
if err != nil { if err != nil {
log.Fatalf("Unable to retrieve token from web %v", err)
logger.Fatalf("Unable to retrieve token from web %v", err)
} }
return tok return tok
} }
@@ -612,12 +614,13 @@ func gDriveTokenFromFile(file string) (*oauth2.Token, error) {
} }


// Saves a token to a file path. // Saves a token to a file path.
func saveGDriveToken(path string, token *oauth2.Token) {
fmt.Printf("Saving credential file to: %s\n", path)
func saveGDriveToken(path string, token *oauth2.Token, logger *log.Logger) {
logger.Printf("Saving credential file to: %s\n", path)
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
defer f.Close() defer f.Close()
if err != nil { if err != nil {
log.Fatalf("Unable to cache oauth token: %v", err)
logger.Fatalf("Unable to cache oauth token: %v", err)
} }

json.NewEncoder(f).Encode(token) json.NewEncoder(f).Encode(token)
} }

+ 2
- 3
server/virustotal.go View File

@@ -27,7 +27,6 @@ package server
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"net/http" "net/http"


_ "github.com/PuerkitoBio/ghost/handlers" _ "github.com/PuerkitoBio/ghost/handlers"
@@ -44,7 +43,7 @@ func (s *Server) virusTotalHandler(w http.ResponseWriter, r *http.Request) {
contentLength := r.ContentLength contentLength := r.ContentLength
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")


log.Printf("Submitting to VirusTotal: %s %d %s", filename, contentLength, contentType)
s.logger.Printf("Submitting to VirusTotal: %s %d %s", filename, contentLength, contentType)


vt, err := virustotal.NewVirusTotal(s.VirusTotalKey) vt, err := virustotal.NewVirusTotal(s.VirusTotalKey)
if err != nil { if err != nil {
@@ -60,6 +59,6 @@ func (s *Server) virusTotalHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), 500)
} }


log.Println(result)
s.logger.Println(result)
w.Write([]byte(fmt.Sprintf("%v\n", result.Permalink))) w.Write([]byte(fmt.Sprintf("%v\n", result.Permalink)))
} }

Loading…
Cancel
Save