mirror of
https://github.com/minio/mc.git
synced 2025-11-12 01:02:26 +03:00
Always make sure to verify argument validation in checkSyntax**.
Cleanup share-upload.go to be aware of different argument validation.
This commit is contained in:
1
ls.go
1
ls.go
@@ -124,6 +124,7 @@ func doList(clnt client.Client, recursive, multipleArgs bool) *probe.Error {
|
||||
if os.IsNotExist(contentCh.Err.ToGoError()) || os.IsPermission(contentCh.Err.ToGoError()) {
|
||||
if contentCh.Content != nil {
|
||||
if contentCh.Content.Type.IsDir() && (contentCh.Content.Type&os.ModeSymlink == os.ModeSymlink) {
|
||||
errorIf(contentCh.Err.Trace(), "Unable to list broken folder link.")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func (f *fsClient) fsStat() (os.FileInfo, *probe.Error) {
|
||||
// Resolve symlinks
|
||||
fpath, err := filepath.EvalSymlinks(fpath)
|
||||
if runtime.GOOS == "windows" {
|
||||
// On windows there are directory symlinks
|
||||
// On windows there are folder symlinks
|
||||
// which are called junction files which
|
||||
// carry special meaning on windows
|
||||
// - which cannot be accessed with regular operations
|
||||
@@ -252,7 +252,7 @@ func (f *fsClient) listInRoutine(contentCh chan client.ContentOnChannel) {
|
||||
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
fi, err = os.Stat(filepath.Join(dir.Name(), fi.Name()))
|
||||
if os.IsPermission(err) {
|
||||
// On windows there are directory symlinks
|
||||
// On windows there are folder symlinks
|
||||
// which are called junction files which
|
||||
// carry special meaning on windows
|
||||
// - which cannot be accessed with regular operations
|
||||
@@ -348,7 +348,7 @@ func (f *fsClient) listRecursiveInRoutine(contentCh chan client.ContentOnChannel
|
||||
}
|
||||
if os.IsPermission(err) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// On windows there are directory symlinks
|
||||
// On windows there are folder symlinks
|
||||
// which are called junction files which
|
||||
// carry special meaning on windows
|
||||
// - which cannot be accessed with regular operations
|
||||
@@ -384,7 +384,7 @@ func (f *fsClient) listRecursiveInRoutine(contentCh chan client.ContentOnChannel
|
||||
if err != nil {
|
||||
if os.IsPermission(err) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// On windows there are directory symlinks
|
||||
// On windows there are folder symlinks
|
||||
// which are called junction files which
|
||||
// carry special meaning on windows
|
||||
// - which cannot be accessed with regular operations
|
||||
|
||||
@@ -89,15 +89,24 @@ func (c *s3Client) ShareDownload(expires time.Duration) (string, *probe.Error) {
|
||||
func (c *s3Client) ShareUpload(recursive bool, expires time.Duration, contentType string) (map[string]string, *probe.Error) {
|
||||
bucket, object := c.url2BucketAndObject()
|
||||
p := minio.NewPostPolicy()
|
||||
p.SetExpires(time.Now().UTC().Add(expires))
|
||||
if len(contentType) > 0 {
|
||||
if err := p.SetExpires(time.Now().UTC().Add(expires)); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
if strings.TrimSpace(contentType) != "" || contentType != "" {
|
||||
// No need to check for errors here, we have trimmed off the spaces
|
||||
p.SetContentType(contentType)
|
||||
}
|
||||
p.SetBucket(bucket)
|
||||
if err := p.SetBucket(bucket); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
if recursive {
|
||||
p.SetKeyStartsWith(object)
|
||||
if err := p.SetKeyStartsWith(object); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
} else {
|
||||
p.SetKey(object)
|
||||
if err := p.SetKey(object); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
m, err := c.api.PresignedPostPolicy(p)
|
||||
return m, probe.NewError(err)
|
||||
|
||||
@@ -89,15 +89,24 @@ func (c *s3Client) ShareDownload(expires time.Duration) (string, *probe.Error) {
|
||||
func (c *s3Client) ShareUpload(recursive bool, expires time.Duration, contentType string) (map[string]string, *probe.Error) {
|
||||
bucket, object := c.url2BucketAndObject()
|
||||
p := minio.NewPostPolicy()
|
||||
p.SetExpires(time.Now().UTC().Add(expires))
|
||||
if len(contentType) > 0 {
|
||||
if err := p.SetExpires(time.Now().UTC().Add(expires)); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
if strings.TrimSpace(contentType) != "" || contentType != "" {
|
||||
// No need to verify for error here, since we have stripped out spaces
|
||||
p.SetContentType(contentType)
|
||||
}
|
||||
p.SetBucket(bucket)
|
||||
if err := p.SetBucket(bucket); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
if recursive {
|
||||
p.SetKeyStartsWith(object)
|
||||
if err := p.SetKeyStartsWith(object); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
} else {
|
||||
p.SetKey(object)
|
||||
if err := p.SetKey(object); err != nil {
|
||||
return nil, probe.NewError(err)
|
||||
}
|
||||
}
|
||||
m, err := c.api.PresignedPostPolicy(p)
|
||||
return m, probe.NewError(err)
|
||||
|
||||
@@ -192,7 +192,7 @@ func mainSession(ctx *cli.Context) {
|
||||
setSessionPalette(ctx.GlobalString("colors"))
|
||||
|
||||
if !isSessionDirExists() {
|
||||
fatalIf(createSessionDir().Trace(), "Unable to create session directory.")
|
||||
fatalIf(createSessionDir().Trace(), "Unable to create session folder.")
|
||||
}
|
||||
|
||||
switch strings.TrimSpace(ctx.Args().First()) {
|
||||
@@ -219,7 +219,7 @@ func mainSession(ctx *cli.Context) {
|
||||
if s.Header.RootPath != "" {
|
||||
// chdir to RootPath
|
||||
e = os.Chdir(s.Header.RootPath)
|
||||
fatalIf(probe.NewError(e), "Unable to change directory to root path while resuming session.")
|
||||
fatalIf(probe.NewError(e), "Unable to change our folder to root path while resuming session.")
|
||||
}
|
||||
sessionExecute(s)
|
||||
err = s.Close()
|
||||
@@ -230,7 +230,7 @@ func mainSession(ctx *cli.Context) {
|
||||
|
||||
// chdir back to saved path
|
||||
e = os.Chdir(savedCwd)
|
||||
fatalIf(probe.NewError(e), "Unable to change directory to saved path ‘"+savedCwd+"’.")
|
||||
fatalIf(probe.NewError(e), "Unable to change our folder to saved path ‘"+savedCwd+"’.")
|
||||
|
||||
// purge a requested pending session, if "all" purge everything
|
||||
case "clear":
|
||||
|
||||
@@ -84,7 +84,7 @@ func mainShareDownload(ctx *cli.Context) {
|
||||
|
||||
// if recursive strip off the "..."
|
||||
err := doShareDownloadURL(stripRecursiveURL(targetURL), isURLRecursive(targetURL), expires)
|
||||
fatalIf(err.Trace(targetURL), "Unable to generate URL for sharing.")
|
||||
fatalIf(err.Trace(targetURL), "Unable to generate URL for download.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -59,6 +59,13 @@ func checkShareUploadSyntax(ctx *cli.Context) {
|
||||
if len(args) > 3 {
|
||||
cli.ShowCommandHelpAndExit(ctx, "upload", 1) // last argument is exit code
|
||||
}
|
||||
url := stripRecursiveURL(strings.TrimSpace(args.Get(0)))
|
||||
if !isObjectKeyPresent(url) {
|
||||
fatalIf(errDummy().Trace(), fmt.Sprintf("Upload location needs object key ‘%s’.", strings.TrimSpace(args.Get(0))))
|
||||
}
|
||||
if strings.HasSuffix(strings.TrimSpace(args.Get(0)), "/") {
|
||||
fatalIf(errDummy().Trace(), fmt.Sprintf("Upload location cannot end with ‘/’. Did you mean ‘%s’.", url+recursiveSeparator))
|
||||
}
|
||||
}
|
||||
|
||||
func mainShareUpload(ctx *cli.Context) {
|
||||
@@ -70,23 +77,19 @@ func mainShareUpload(ctx *cli.Context) {
|
||||
|
||||
args := ctx.Args()
|
||||
config := mustGetMcConfig()
|
||||
url := args.Get(0)
|
||||
if strings.HasSuffix(url, "/") {
|
||||
fatalIf(errDummy().Trace(), fmt.Sprintf("Upload location can not end with '/'. Did you mean %s%s", url, recursiveSeparator))
|
||||
}
|
||||
if len(args.Get(1)) == 0 {
|
||||
if strings.TrimSpace(args.Get(1)) == "" {
|
||||
expires = time.Duration(604800) * time.Second
|
||||
} else {
|
||||
expires, err = time.ParseDuration(args.Get(1))
|
||||
expires, err = time.ParseDuration(strings.TrimSpace(args.Get(1)))
|
||||
if err != nil {
|
||||
fatalIf(probe.NewError(err), "Unable to parse time argument.")
|
||||
}
|
||||
}
|
||||
contentType := args.Get(2)
|
||||
targetURL := getAliasURL(url, config.Aliases)
|
||||
contentType := strings.TrimSpace(args.Get(2))
|
||||
targetURL := getAliasURL(strings.TrimSpace(args.Get(0)), config.Aliases)
|
||||
|
||||
e := doShareUploadURL(stripRecursiveURL(targetURL), isURLRecursive(targetURL), expires, contentType)
|
||||
fatalIf(e.Trace(targetURL), "Unable to generate URL for sharing.")
|
||||
fatalIf(e.Trace(targetURL), "Unable to generate URL for upload.")
|
||||
}
|
||||
|
||||
// doShareURL share files from target
|
||||
30
share.go
30
share.go
@@ -33,9 +33,9 @@ import (
|
||||
func shareDataDirSetup() {
|
||||
if !isSharedURLsDataDirExists() {
|
||||
shareDir, err := getSharedURLsDataDir()
|
||||
fatalIf(err.Trace(), "Unable to get shared URL data directory")
|
||||
fatalIf(err.Trace(), "Unable to get shared URL data folder.")
|
||||
|
||||
fatalIf(createSharedURLsDataDir().Trace(), "Unable to create shared URL data directory ‘"+shareDir+"’.")
|
||||
fatalIf(createSharedURLsDataDir().Trace(), "Unable to create shared URL data folder ‘"+shareDir+"’.")
|
||||
}
|
||||
if !isSharedURLsDataFileExists() {
|
||||
shareFile, err := getSharedURLsDataFile()
|
||||
@@ -217,6 +217,32 @@ func path2Bucket(u *client.URL) (bucketName string) {
|
||||
return bucketName
|
||||
}
|
||||
|
||||
// this code is necessary since, share only operates on cloud storage URLs not filesystem
|
||||
func isObjectKeyPresent(url string) bool {
|
||||
u := client.NewURL(url)
|
||||
path := u.Path
|
||||
match, _ := filepath.Match("*.s3*.amazonaws.com", u.Host)
|
||||
switch {
|
||||
case match == true:
|
||||
hostSplits := strings.SplitN(u.Host, ".", 2)
|
||||
path = string(u.Separator) + hostSplits[0] + u.Path
|
||||
}
|
||||
pathSplits := strings.SplitN(path, "?", 2)
|
||||
splits := strings.SplitN(pathSplits[0], string(u.Separator), 3)
|
||||
switch len(splits) {
|
||||
case 0, 1:
|
||||
return false
|
||||
case 2:
|
||||
return false
|
||||
case 3:
|
||||
if splits[2] == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func setSharePalette(style string) {
|
||||
console.SetCustomPalette(map[string]*color.Color{
|
||||
"Share": color.New(color.FgGreen, color.Bold),
|
||||
|
||||
@@ -81,17 +81,18 @@ func (sl *sortedList) Create(clnt client.Client, id string) *probe.Error {
|
||||
switch err := content.Err.ToGoError().(type) {
|
||||
case client.BrokenSymlink:
|
||||
// FIXME: send the error to caller using channel
|
||||
errorIf(content.Err.Trace(), fmt.Sprintf("Skipping broken Symlink ‘%s’.", err.Path))
|
||||
errorIf(content.Err.Trace(), fmt.Sprintf("Skipping broken symlink ‘%s’.", err.Path))
|
||||
continue
|
||||
case client.TooManyLevelsSymlink:
|
||||
// FIXME: send the error to caller using channel
|
||||
errorIf(content.Err.Trace(), fmt.Sprintf("Skipping too many levels Symlink ‘%s’.", err.Path))
|
||||
errorIf(content.Err.Trace(), fmt.Sprintf("Skipping too many levels symlink ‘%s’.", err.Path))
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(content.Err.ToGoError()) || os.IsPermission(content.Err.ToGoError()) {
|
||||
// FIXME: abstract this at fs.go layer
|
||||
if content.Content != nil {
|
||||
if content.Content.Type.IsDir() && (content.Content.Type&os.ModeSymlink == os.ModeSymlink) {
|
||||
errorIf(content.Err.Trace(), fmt.Sprintf("Skipping broken folder symlink ‘%s’.", content.Content.Name))
|
||||
continue
|
||||
}
|
||||
errorIf(content.Err.Trace(), fmt.Sprintf("Skipping ‘%s’.", content.Content.Name))
|
||||
|
||||
Reference in New Issue
Block a user