1
0
mirror of https://github.com/minio/mc.git synced 2025-11-12 01:02:26 +03:00
Files
mc/share-main.go
2015-08-23 01:24:04 -07:00

165 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Minio Client (C) 2014, 2015 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"path/filepath"
"strings"
"time"
"github.com/fatih/color"
"github.com/minio/cli"
"github.com/minio/mc/pkg/client"
"github.com/minio/mc/pkg/console"
"github.com/minio/minio/pkg/probe"
)
// Help message.
var shareCmd = cli.Command{
Name: "share",
Usage: "Share documents via URL",
Action: mainShare,
CustomHelpTemplate: `NAME:
mc {{.Name}} - {{.Usage}}
USAGE:
mc {{.Name}} TARGET [DURATION=s|m|h|d] {{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if .Flags}}
FLAGS:
{{range .Flags}}{{.}}
{{end}}{{ end }}
EXAMPLES:
1. Generate URL for sharing, with a default expiry of 7 days.
$ mc {{.Name}} https://s3.amazonaws.com/backup/2006-Mar-1/backup.tar.gz
2. Generate URL for sharing, with an expiry of 10 minutes.
$ mc {{.Name}} https://s3.amazonaws.com/backup/2006-Mar-1/backup.tar.gz 10m
3. Generate list of URLs for sharing a folder recursively, with expiration of 1 hour each.
$ mc {{.Name}} https://s3.amazonaws.com/backup... 1h
`,
}
// mainShare - is a handler for mc share command
func mainShare(ctx *cli.Context) {
if !ctx.Args().Present() || ctx.Args().First() == "help" || len(ctx.Args()) > 2 {
cli.ShowCommandHelpAndExit(ctx, "share", 1) // last argument is exit code
}
console.SetCustomTheme(map[string]*color.Color{
"Share": color.New(color.FgGreen, color.Bold),
})
args := ctx.Args()
config := mustGetMcConfig()
/// get first and last arguments
url := args.First() // url to be shared
// default expiration is 7days
expires := time.Duration(604800) * time.Second
if len(args) == 2 {
var err error
expires, err = time.ParseDuration(args.Last())
fatalIf(probe.NewError(err), "Unable to parse time argument.")
}
targetURL, err := getCanonicalizedURL(url, config.Aliases)
fatalIf(err.Trace(url), "Unable to parse argument "+url+".")
// if recursive strip off the "..."
err = doShareCmd(stripRecursiveURL(targetURL), isURLRecursive(targetURL), expires)
fatalIf(err.Trace(targetURL), "Unable generate URL for sharing.")
}
// ShareMessage container for share messages
type ShareMessage struct {
Expires time.Duration `json:"expire-seconds"`
PresignedURL string `json:"presigned-url"`
}
// String string printer for share message
func (s ShareMessage) String() string {
if !globalJSONFlag {
return console.Colorize("Share", fmt.Sprintf("Succesfully generated shared URL with expiry %s, please share: %s", s.Expires, s.PresignedURL))
}
shareMessageBytes, err := json.Marshal(s)
fatalIf(probe.NewError(err), "Failed to marshal into JSON.")
// json encoding escapes ampersand into its unicode character which is not usable directly for share
// and fails with cloud storage. convert them back so that they are usable
shareMessageBytes = bytes.Replace(shareMessageBytes, []byte("\\u0026"), []byte("&"), -1)
return string(shareMessageBytes)
}
func getNewTargetURL(targetParser *client.URL, name string) string {
match, _ := filepath.Match("*.s3*.amazonaws.com", targetParser.Host)
if match {
targetParser.Path = string(targetParser.Separator) + name
} else {
targetParser.Path = string(targetParser.Separator) + path2Bucket(targetParser) + string(targetParser.Separator) + name
}
return targetParser.String()
}
// doShareCmd share files from target
func doShareCmd(targetURL string, recursive bool, expires time.Duration) *probe.Error {
clnt, err := target2Client(targetURL)
if err != nil {
return err.Trace()
}
if expires.Seconds() < 1 {
return probe.NewError(errors.New("Too low expires, expiration cannot be less than 1 second."))
}
if expires.Seconds() > 604800 {
return probe.NewError(errors.New("Too high expires, expiration cannot be larger than 7 days."))
}
for contentCh := range clnt.List(recursive) {
if contentCh.Err != nil {
return contentCh.Err.Trace()
}
newClnt, err := url2Client(getNewTargetURL(clnt.URL(), contentCh.Content.Name))
if err != nil {
return err.Trace()
}
presignedURL, err := newClnt.Share(expires)
if err != nil {
return err.Trace()
}
console.Println(ShareMessage{Expires: expires / time.Second, PresignedURL: presignedURL}.String())
}
return nil
}
func path2Bucket(u *client.URL) (bucketName string) {
pathSplits := strings.SplitN(u.Path, "?", 2)
splits := strings.SplitN(pathSplits[0], string(u.Separator), 3)
switch len(splits) {
case 0, 1:
bucketName = ""
case 2:
bucketName = splits[1]
case 3:
bucketName = splits[1]
}
return bucketName
}