all: update gdrive client and various linting cleanups (#497)
This commit is contained in:
parent
21812d3efc
commit
64c7759126
|
@ -300,7 +300,7 @@ type Cmd struct {
|
|||
*cli.App
|
||||
}
|
||||
|
||||
func versionCommand(ctx *cli.Context) {
|
||||
func versionCommand(_ *cli.Context) {
|
||||
fmt.Println(color.YellowString("transfer.sh %s: Easy file sharing from the command line", Version))
|
||||
}
|
||||
|
||||
|
@ -470,7 +470,7 @@ func New() *Cmd {
|
|||
options = append(options, server.UseStorage(store))
|
||||
}
|
||||
case "gdrive":
|
||||
chunkSize := c.Int("gdrive-chunk-size")
|
||||
chunkSize := c.Int("gdrive-chunk-size") * 1024 * 1024
|
||||
|
||||
if clientJSONFilepath := c.String("gdrive-client-json-filepath"); clientJSONFilepath == "" {
|
||||
panic("client-json-filepath not set.")
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
clamd "github.com/dutchcoders/go-clamd"
|
||||
"github.com/dutchcoders/go-clamd"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/dutchcoders/transfer.sh/server/storage"
|
||||
"html"
|
||||
html_template "html/template"
|
||||
htmlTemplate "html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
|
@ -51,13 +51,13 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
text_template "text/template"
|
||||
textTemplate "text/template"
|
||||
"time"
|
||||
|
||||
web "github.com/dutchcoders/transfer.sh-web"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
blackfriday "github.com/russross/blackfriday/v2"
|
||||
"github.com/russross/blackfriday/v2"
|
||||
"github.com/skip2/go-qrcode"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
@ -73,24 +73,24 @@ func stripPrefix(path string) string {
|
|||
return strings.Replace(path, web.Prefix+"/", "", -1)
|
||||
}
|
||||
|
||||
func initTextTemplates() *text_template.Template {
|
||||
templateMap := text_template.FuncMap{"format": formatNumber}
|
||||
func initTextTemplates() *textTemplate.Template {
|
||||
templateMap := textTemplate.FuncMap{"format": formatNumber}
|
||||
|
||||
// Templates with functions available to them
|
||||
var templates = text_template.New("").Funcs(templateMap)
|
||||
var templates = textTemplate.New("").Funcs(templateMap)
|
||||
return templates
|
||||
}
|
||||
|
||||
func initHTMLTemplates() *html_template.Template {
|
||||
templateMap := html_template.FuncMap{"format": formatNumber}
|
||||
func initHTMLTemplates() *htmlTemplate.Template {
|
||||
templateMap := htmlTemplate.FuncMap{"format": formatNumber}
|
||||
|
||||
// Templates with functions available to them
|
||||
var templates = html_template.New("").Funcs(templateMap)
|
||||
var templates = htmlTemplate.New("").Funcs(templateMap)
|
||||
|
||||
return templates
|
||||
}
|
||||
|
||||
func healthHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func healthHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
_, _ = w.Write([]byte("Approaching Neutral Zone, all systems normal and functioning."))
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
var templatePath string
|
||||
var content html_template.HTML
|
||||
var content htmlTemplate.HTML
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(contentType, "image/"):
|
||||
|
@ -166,9 +166,9 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if strings.HasPrefix(contentType, "text/x-markdown") || strings.HasPrefix(contentType, "text/markdown") {
|
||||
unsafe := blackfriday.Run(data)
|
||||
output := bluemonday.UGCPolicy().SanitizeBytes(unsafe)
|
||||
content = html_template.HTML(output)
|
||||
content = htmlTemplate.HTML(output)
|
||||
} else if strings.HasPrefix(contentType, "text/plain") {
|
||||
content = html_template.HTML(fmt.Sprintf("<pre>%s</pre>", html.EscapeString(string(data))))
|
||||
content = htmlTemplate.HTML(fmt.Sprintf("<pre>%s</pre>", html.EscapeString(string(data))))
|
||||
} else {
|
||||
templatePath = "download.sandbox.html"
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
data := struct {
|
||||
ContentType string
|
||||
Content html_template.HTML
|
||||
Content htmlTemplate.HTML
|
||||
Filename string
|
||||
URL string
|
||||
URLGet string
|
||||
|
@ -282,7 +282,7 @@ func (s *Server) viewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Server) notFoundHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *Server) notFoundHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
http.Error(w, http.StatusText(404), 404)
|
||||
}
|
||||
|
||||
|
@ -303,15 +303,15 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
responseBody := ""
|
||||
|
||||
for _, fheaders := range r.MultipartForm.File {
|
||||
for _, fheader := range fheaders {
|
||||
filename := sanitize(fheader.Filename)
|
||||
contentType := mime.TypeByExtension(filepath.Ext(fheader.Filename))
|
||||
for _, fHeaders := range r.MultipartForm.File {
|
||||
for _, fHeader := range fHeaders {
|
||||
filename := sanitize(fHeader.Filename)
|
||||
contentType := mime.TypeByExtension(filepath.Ext(fHeader.Filename))
|
||||
|
||||
var f io.Reader
|
||||
var err error
|
||||
|
||||
if f, err = fheader.Open(); err != nil {
|
||||
if f, err = fHeader.Open(); err != nil {
|
||||
s.logger.Printf("%s", err.Error())
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
|
|
@ -88,10 +88,10 @@ func (f *ipFilter) BlockIP(ip string) bool {
|
|||
}
|
||||
|
||||
func (f *ipFilter) ToggleIP(str string, allowed bool) bool {
|
||||
//check if has subnet
|
||||
if ip, net, err := net.ParseCIDR(str); err == nil {
|
||||
//check if provided string describes a subnet
|
||||
if ip, network, err := net.ParseCIDR(str); err == nil {
|
||||
// containing only one ip?
|
||||
if n, total := net.Mask.Size(); n == total {
|
||||
if n, total := network.Mask.Size(); n == total {
|
||||
f.mut.Lock()
|
||||
f.ips[ip.String()] = allowed
|
||||
f.mut.Unlock()
|
||||
|
@ -110,7 +110,7 @@ func (f *ipFilter) ToggleIP(str string, allowed bool) bool {
|
|||
if !found {
|
||||
f.subnets = append(f.subnets, &subnet{
|
||||
str: str,
|
||||
ipnet: net,
|
||||
ipnet: network,
|
||||
allowed: allowed,
|
||||
})
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ func (f *ipFilter) NetBlocked(ip net.IP) bool {
|
|||
return !f.NetAllowed(ip)
|
||||
}
|
||||
|
||||
//WrapIPFilter the provided handler with simple IP blocking middleware
|
||||
//Wrap the provided handler with simple IP blocking middleware
|
||||
//using this IP filter and its configuration
|
||||
func (f *ipFilter) Wrap(next http.Handler) http.Handler {
|
||||
return &ipFilterMiddleware{ipFilter: f, next: next}
|
||||
|
|
|
@ -26,7 +26,7 @@ package server
|
|||
|
||||
import (
|
||||
"context"
|
||||
crypto_rand "crypto/rand"
|
||||
cryptoRand "crypto/rand"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
@ -381,7 +381,7 @@ func New(options ...OptionFn) (*Server, error) {
|
|||
|
||||
func init() {
|
||||
var seedBytes [8]byte
|
||||
if _, err := crypto_rand.Read(seedBytes[:]); err != nil {
|
||||
if _, err := cryptoRand.Read(seedBytes[:]); err != nil {
|
||||
panic("cannot obtain cryptographically secure seed")
|
||||
}
|
||||
rand.Seed(int64(binary.LittleEndian.Uint64(seedBytes[:])))
|
||||
|
@ -475,7 +475,7 @@ func (s *Server) Run() {
|
|||
return false
|
||||
}
|
||||
|
||||
match = (r.Referer() == "")
|
||||
match = r.Referer() == ""
|
||||
|
||||
u, err := url.Parse(r.Referer())
|
||||
if err != nil {
|
||||
|
|
|
@ -15,8 +15,9 @@ import (
|
|||
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
drive "google.golang.org/api/drive/v3"
|
||||
"google.golang.org/api/drive/v3"
|
||||
"google.golang.org/api/googleapi"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
// GDrive is a storage backed by GDrive
|
||||
|
@ -29,8 +30,15 @@ type GDrive struct {
|
|||
logger *log.Logger
|
||||
}
|
||||
|
||||
const gDriveRootConfigFile = "root_id.conf"
|
||||
const gDriveTokenJSONFile = "token.json"
|
||||
const gDriveDirectoryMimeType = "application/vnd.google-apps.folder"
|
||||
|
||||
// NewGDriveStorage is the factory for GDrive
|
||||
func NewGDriveStorage(clientJSONFilepath string, localConfigPath string, basedir string, chunkSize int, logger *log.Logger) (*GDrive, error) {
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
b, err := ioutil.ReadFile(clientJSONFilepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -42,13 +50,13 @@ func NewGDriveStorage(clientJSONFilepath string, localConfigPath string, basedir
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// ToDo: Upgrade deprecated version
|
||||
srv, err := drive.New(getGDriveClient(context.TODO(), config, localConfigPath, logger)) // nolint: staticcheck
|
||||
httpClient := getGDriveClient(ctx, config, localConfigPath, logger)
|
||||
|
||||
srv, err := drive.NewService(ctx, option.WithHTTPClient(httpClient))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chunkSize = chunkSize * 1024 * 1024
|
||||
storage := &GDrive{service: srv, basedir: basedir, rootID: "", localConfigPath: localConfigPath, chunkSize: chunkSize, logger: logger}
|
||||
err = storage.setupRoot()
|
||||
if err != nil {
|
||||
|
@ -58,12 +66,8 @@ func NewGDriveStorage(clientJSONFilepath string, localConfigPath string, basedir
|
|||
return storage, nil
|
||||
}
|
||||
|
||||
const gdriveRootConfigFile = "root_id.conf"
|
||||
const gdriveTokenJSONFile = "token.json"
|
||||
const gdriveDirectoryMimeType = "application/vnd.google-apps.folder"
|
||||
|
||||
func (s *GDrive) setupRoot() error {
|
||||
rootFileConfig := filepath.Join(s.localConfigPath, gdriveRootConfigFile)
|
||||
rootFileConfig := filepath.Join(s.localConfigPath, gDriveRootConfigFile)
|
||||
|
||||
rootID, err := ioutil.ReadFile(rootFileConfig)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
|
@ -77,7 +81,7 @@ func (s *GDrive) setupRoot() error {
|
|||
|
||||
dir := &drive.File{
|
||||
Name: s.basedir,
|
||||
MimeType: gdriveDirectoryMimeType,
|
||||
MimeType: gDriveDirectoryMimeType,
|
||||
}
|
||||
|
||||
di, err := s.service.Files.Create(dir).Fields("id").Do()
|
||||
|
@ -108,7 +112,7 @@ func (s *GDrive) findID(filename string, token string) (string, error) {
|
|||
|
||||
fileID, tokenID, nextPageToken := "", "", ""
|
||||
|
||||
q := fmt.Sprintf("'%s' in parents and name='%s' and mimeType='%s' and trashed=false", s.rootID, token, gdriveDirectoryMimeType)
|
||||
q := fmt.Sprintf("'%s' in parents and name='%s' and mimeType='%s' and trashed=false", s.rootID, token, gDriveDirectoryMimeType)
|
||||
l, err := s.list(nextPageToken, q)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -136,7 +140,7 @@ func (s *GDrive) findID(filename string, token string) (string, error) {
|
|||
return "", fmt.Errorf("cannot find file %s/%s", token, filename)
|
||||
}
|
||||
|
||||
q = fmt.Sprintf("'%s' in parents and name='%s' and mimeType!='%s' and trashed=false", tokenID, filename, gdriveDirectoryMimeType)
|
||||
q = fmt.Sprintf("'%s' in parents and name='%s' and mimeType!='%s' and trashed=false", tokenID, filename, gDriveDirectoryMimeType)
|
||||
l, err = s.list(nextPageToken, q)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -180,7 +184,7 @@ func (s *GDrive) Head(ctx context.Context, token string, filename string) (conte
|
|||
}
|
||||
|
||||
var fi *drive.File
|
||||
if fi, err = s.service.Files.Get(fileID).Fields("size").Do(); err != nil {
|
||||
if fi, err = s.service.Files.Get(fileID).Context(ctx).Fields("size").Do(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -231,7 +235,7 @@ func (s *GDrive) Delete(ctx context.Context, token string, filename string) (err
|
|||
return
|
||||
}
|
||||
|
||||
err = s.service.Files.Delete(fileID).Do()
|
||||
err = s.service.Files.Delete(fileID).Context(ctx).Do()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -240,7 +244,7 @@ func (s *GDrive) Purge(ctx context.Context, days time.Duration) (err error) {
|
|||
nextPageToken := ""
|
||||
|
||||
expirationDate := time.Now().Add(-1 * days).Format(time.RFC3339)
|
||||
q := fmt.Sprintf("'%s' in parents and modifiedTime < '%s' and mimeType!='%s' and trashed=false", s.rootID, expirationDate, gdriveDirectoryMimeType)
|
||||
q := fmt.Sprintf("'%s' in parents and modifiedTime < '%s' and mimeType!='%s' and trashed=false", s.rootID, expirationDate, gDriveDirectoryMimeType)
|
||||
l, err := s.list(nextPageToken, q)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -248,7 +252,7 @@ func (s *GDrive) Purge(ctx context.Context, days time.Duration) (err error) {
|
|||
|
||||
for 0 < len(l.Files) {
|
||||
for _, fi := range l.Files {
|
||||
err = s.service.Files.Delete(fi.Id).Do()
|
||||
err = s.service.Files.Delete(fi.Id).Context(ctx).Do()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -291,7 +295,7 @@ func (s *GDrive) Put(ctx context.Context, token string, filename string, reader
|
|||
dir := &drive.File{
|
||||
Name: token,
|
||||
Parents: []string{s.rootID},
|
||||
MimeType: gdriveDirectoryMimeType,
|
||||
MimeType: gDriveDirectoryMimeType,
|
||||
Size: int64(contentLength),
|
||||
}
|
||||
|
||||
|
@ -321,7 +325,7 @@ func (s *GDrive) Put(ctx context.Context, token string, filename string, reader
|
|||
|
||||
// Retrieve a token, saves the token, then returns the generated client.
|
||||
func getGDriveClient(ctx context.Context, config *oauth2.Config, localConfigPath string, logger *log.Logger) *http.Client {
|
||||
tokenFile := filepath.Join(localConfigPath, gdriveTokenJSONFile)
|
||||
tokenFile := filepath.Join(localConfigPath, gDriveTokenJSONFile)
|
||||
tok, err := gDriveTokenFromFile(tokenFile)
|
||||
if err != nil {
|
||||
tok = getGDriveTokenFromWeb(ctx, config, logger)
|
||||
|
|
|
@ -28,7 +28,7 @@ func (s *LocalStorage) Type() string {
|
|||
}
|
||||
|
||||
// Head retrieves content length of a file from storage
|
||||
func (s *LocalStorage) Head(ctx context.Context, token string, filename string) (contentLength uint64, err error) {
|
||||
func (s *LocalStorage) Head(_ context.Context, token string, filename string) (contentLength uint64, err error) {
|
||||
path := filepath.Join(s.basedir, token, filename)
|
||||
|
||||
var fi os.FileInfo
|
||||
|
@ -42,7 +42,7 @@ func (s *LocalStorage) Head(ctx context.Context, token string, filename string)
|
|||
}
|
||||
|
||||
// Get retrieves a file from storage
|
||||
func (s *LocalStorage) Get(ctx context.Context, token string, filename string) (reader io.ReadCloser, contentLength uint64, err error) {
|
||||
func (s *LocalStorage) Get(_ context.Context, token string, filename string) (reader io.ReadCloser, contentLength uint64, err error) {
|
||||
path := filepath.Join(s.basedir, token, filename)
|
||||
|
||||
// content type , content length
|
||||
|
@ -61,7 +61,7 @@ func (s *LocalStorage) Get(ctx context.Context, token string, filename string) (
|
|||
}
|
||||
|
||||
// Delete removes a file from storage
|
||||
func (s *LocalStorage) Delete(ctx context.Context, token string, filename string) (err error) {
|
||||
func (s *LocalStorage) Delete(_ context.Context, token string, filename string) (err error) {
|
||||
metadata := filepath.Join(s.basedir, token, fmt.Sprintf("%s.metadata", filename))
|
||||
_ = os.Remove(metadata)
|
||||
|
||||
|
@ -71,7 +71,7 @@ func (s *LocalStorage) Delete(ctx context.Context, token string, filename string
|
|||
}
|
||||
|
||||
// Purge cleans up the storage
|
||||
func (s *LocalStorage) Purge(ctx context.Context, days time.Duration) (err error) {
|
||||
func (s *LocalStorage) Purge(_ context.Context, days time.Duration) (err error) {
|
||||
err = filepath.Walk(s.basedir,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
@ -102,7 +102,7 @@ func (s *LocalStorage) IsNotExist(err error) bool {
|
|||
}
|
||||
|
||||
// Put saves a file on storage
|
||||
func (s *LocalStorage) Put(ctx context.Context, token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
||||
func (s *LocalStorage) Put(_ context.Context, token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
||||
var f io.WriteCloser
|
||||
var err error
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ func (s *S3Storage) Head(ctx context.Context, token string, filename string) (co
|
|||
}
|
||||
|
||||
// Purge cleans up the storage
|
||||
func (s *S3Storage) Purge(ctx context.Context, days time.Duration) (err error) {
|
||||
func (s *S3Storage) Purge(context.Context, time.Duration) (err error) {
|
||||
// NOOP expiration is set at upload time
|
||||
return nil
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ func (s *S3Storage) Delete(ctx context.Context, token string, filename string) (
|
|||
}
|
||||
|
||||
// Put saves a file on storage
|
||||
func (s *S3Storage) Put(ctx context.Context, token string, filename string, reader io.Reader, contentType string, contentLength uint64) (err error) {
|
||||
func (s *S3Storage) Put(ctx context.Context, token string, filename string, reader io.Reader, contentType string, _ uint64) (err error) {
|
||||
key := fmt.Sprintf("%s/%s", token, filename)
|
||||
|
||||
s.logger.Printf("Uploading file %s to S3 Bucket", filename)
|
||||
|
@ -159,10 +159,11 @@ func (s *S3Storage) Put(ctx context.Context, token string, filename string, read
|
|||
}
|
||||
|
||||
_, err = uploader.UploadWithContext(ctx, &s3manager.UploadInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(key),
|
||||
Body: reader,
|
||||
Expires: expire,
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(key),
|
||||
Body: reader,
|
||||
Expires: expire,
|
||||
ContentType: aws.String(contentType),
|
||||
})
|
||||
|
||||
return
|
||||
|
|
|
@ -83,7 +83,9 @@ func (s *StorjStorage) Get(ctx context.Context, token string, filename string) (
|
|||
|
||||
s.logger.Printf("Getting file %s from Storj Bucket", filename)
|
||||
|
||||
download, err := s.project.DownloadObject(fpath.WithTempData(ctx, "", true), s.bucket.Name, key, nil)
|
||||
options := uplink.DownloadOptions{}
|
||||
|
||||
download, err := s.project.DownloadObject(fpath.WithTempData(ctx, "", true), s.bucket.Name, key, &options)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
@ -106,7 +108,7 @@ func (s *StorjStorage) Delete(ctx context.Context, token string, filename string
|
|||
}
|
||||
|
||||
// Purge cleans up the storage
|
||||
func (s *StorjStorage) Purge(ctx context.Context, days time.Duration) (err error) {
|
||||
func (s *StorjStorage) Purge(context.Context, time.Duration) (err error) {
|
||||
// NOOP expiration is set at upload time
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -189,10 +188,6 @@ func renderFloat(format string, n float64) string {
|
|||
return signStr + intStr + decimalStr + fracStr
|
||||
}
|
||||
|
||||
func renderInteger(format string, n int) string {
|
||||
return renderFloat(format, float64(n))
|
||||
}
|
||||
|
||||
// Request.RemoteAddress contains port, which we want to remove i.e.:
|
||||
// "[::1]:58292" => "[::1]"
|
||||
func ipAddrFromRemoteAddr(s string) string {
|
||||
|
@ -203,45 +198,16 @@ func ipAddrFromRemoteAddr(s string) string {
|
|||
return s[:idx]
|
||||
}
|
||||
|
||||
func getIPAddress(r *http.Request) string {
|
||||
hdr := r.Header
|
||||
hdrRealIP := hdr.Get("X-Real-Ip")
|
||||
hdrForwardedFor := hdr.Get("X-Forwarded-For")
|
||||
if hdrRealIP == "" && hdrForwardedFor == "" {
|
||||
return ipAddrFromRemoteAddr(r.RemoteAddr)
|
||||
}
|
||||
if hdrForwardedFor != "" {
|
||||
// X-Forwarded-For is potentially a list of addresses separated with ","
|
||||
parts := strings.Split(hdrForwardedFor, ",")
|
||||
for i, p := range parts {
|
||||
parts[i] = strings.TrimSpace(p)
|
||||
}
|
||||
|
||||
// TODO: should return first non-local address
|
||||
return parts[0]
|
||||
}
|
||||
return hdrRealIP
|
||||
}
|
||||
|
||||
func encodeRFC2047(s string) string {
|
||||
// use mail's rfc2047 to encode any string
|
||||
addr := mail.Address{
|
||||
Name: s,
|
||||
Address: "",
|
||||
}
|
||||
return strings.Trim(addr.String(), " <>")
|
||||
}
|
||||
|
||||
func acceptsHTML(hdr http.Header) bool {
|
||||
actual := header.ParseAccept(hdr, "Accept")
|
||||
|
||||
for _, s := range actual {
|
||||
if s.Value == "text/html" {
|
||||
return (true)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return (false)
|
||||
return false
|
||||
}
|
||||
|
||||
func formatSize(size int64) string {
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
virustotal "github.com/dutchcoders/go-virustotal"
|
||||
"github.com/dutchcoders/go-virustotal"
|
||||
)
|
||||
|
||||
func (s *Server) virusTotalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
Loading…
Reference in New Issue