From dbb540890614f39b48478dd8d7de2059b4bdb2c5 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 24 Jan 2017 20:28:51 -0800 Subject: [PATCH 01/75] Add ARM64 build binary for README.md Fixes #3626 --- README.md | 2 ++ README_ZH.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 82b508ecb..1f2540c6c 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,8 @@ chmod 755 minio |GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio| ||32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio| ||32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio| +||64-bit ARM|https://dl.minio.io/server/minio/release/linux-arm64/minio| +||32-bit ARMv6|https://dl.minio.io/server/minio/release/linux-arm6vl/minio| ```sh chmod +x minio ./minio server ~/Photos diff --git a/README_ZH.md b/README_ZH.md index 8e911a4ae..05d463920 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -11,6 +11,8 @@ Minio是一个非常轻量的服务,可以很简单的和其他应用的结合 |GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio| ||32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio| ||32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio| +||64-bit ARM|https://dl.minio.io/server/minio/release/linux-arm64/minio| +||32-bit ARMv6|https://dl.minio.io/server/minio/release/linux-arm6vl/minio| |Apple OS X|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio| |Microsoft Windows|64-bit|https://dl.minio.io/server/minio/release/windows-amd64/minio.exe| ||32-bit|https://dl.minio.io/server/minio/release/windows-386/minio.exe| From 76b8abcd8e6f3f35bec25604ea39b98507a28a1b Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 25 Jan 2017 18:58:49 +0100 Subject: [PATCH 02/75] madmin: Fix args order in listObjectsHeal() (#3629) The order of marker and delimiter and in listObjectsHeal() internal function are switched. That will give wrong result in case of a non recursive objects heal list. --- pkg/madmin/heal-commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/madmin/heal-commands.go b/pkg/madmin/heal-commands.go index 34128345f..09a2f791b 100644 --- a/pkg/madmin/heal-commands.go +++ b/pkg/madmin/heal-commands.go @@ -182,7 +182,7 @@ func mkHealQueryVal(bucket, prefix, marker, delimiter, maxKeyStr string) url.Val } // listObjectsHeal - issues heal list API request for a batch of maxKeys objects to be healed. -func (adm *AdminClient) listObjectsHeal(bucket, prefix, delimiter, marker string, maxKeys int) (listBucketHealResult, error) { +func (adm *AdminClient) listObjectsHeal(bucket, prefix, marker, delimiter string, maxKeys int) (listBucketHealResult, error) { // Construct query params. maxKeyStr := fmt.Sprintf("%d", maxKeys) queryVal := mkHealQueryVal(bucket, prefix, marker, delimiter, maxKeyStr) From 82373e3d50ea1c64ed68f70ba8a05a0b87b4ea88 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Wed, 25 Jan 2017 12:29:06 -0800 Subject: [PATCH 03/75] fs: cleanup - do not cache size of metafiles (#3630) * Remove Size() method and size field from lock.LockedFile * WriteTo method of fsMeta and uploadsV1 now takes concrete type *lock.LockedFile --- cmd/fs-v1-metadata.go | 15 ++++++++++----- cmd/fs-v1-metadata_test.go | 9 +++------ cmd/fs-v1-multipart-common.go | 4 ++-- cmd/fs-v1-multipart.go | 8 ++++---- cmd/fs-v1.go | 2 +- cmd/object-api-multipart-common.go | 14 +++++++++----- pkg/lock/lock.go | 9 +-------- pkg/lock/lock_nix.go | 2 +- pkg/lock/lock_test.go | 3 --- pkg/lock/lock_windows.go | 2 +- 10 files changed, 32 insertions(+), 36 deletions(-) diff --git a/cmd/fs-v1-metadata.go b/cmd/fs-v1-metadata.go index ae0b3532a..f467991db 100644 --- a/cmd/fs-v1-metadata.go +++ b/cmd/fs-v1-metadata.go @@ -125,18 +125,18 @@ func (m *fsMetaV1) AddObjectPart(partNumber int, partName string, partETag strin sort.Sort(byObjectPartNumber(m.Parts)) } -func (m *fsMetaV1) WriteTo(writer io.Writer) (n int64, err error) { +func (m *fsMetaV1) WriteTo(lk *lock.LockedFile) (n int64, err error) { var metadataBytes []byte metadataBytes, err = json.Marshal(m) if err != nil { return 0, traceError(err) } - if err = writer.(*lock.LockedFile).Truncate(0); err != nil { + if err = lk.Truncate(0); err != nil { return 0, traceError(err) } - if _, err = writer.Write(metadataBytes); err != nil { + if _, err = lk.Write(metadataBytes); err != nil { return 0, traceError(err) } @@ -144,9 +144,14 @@ func (m *fsMetaV1) WriteTo(writer io.Writer) (n int64, err error) { return int64(len(metadataBytes)), nil } -func (m *fsMetaV1) ReadFrom(reader io.Reader) (n int64, err error) { +func (m *fsMetaV1) ReadFrom(lk *lock.LockedFile) (n int64, err error) { var metadataBytes []byte - metadataBytes, err = ioutil.ReadAll(reader) + fi, err := lk.Stat() + if err != nil { + return 0, traceError(err) + } + + metadataBytes, err = ioutil.ReadAll(io.NewSectionReader(lk, 0, fi.Size())) if err != nil { return 0, traceError(err) } diff --git a/cmd/fs-v1-metadata_test.go b/cmd/fs-v1-metadata_test.go index b1163d62f..c31008949 100644 --- a/cmd/fs-v1-metadata_test.go +++ b/cmd/fs-v1-metadata_test.go @@ -18,7 +18,6 @@ package cmd import ( "bytes" - "io" "os" "path/filepath" "testing" @@ -69,10 +68,9 @@ func TestReadFSMetadata(t *testing.T) { } defer rlk.Close() - sectionReader := io.NewSectionReader(rlk, 0, rlk.Size()) // Regular fs metadata reading, no errors expected fsMeta := fsMetaV1{} - if _, err = fsMeta.ReadFrom(sectionReader); err != nil { + if _, err = fsMeta.ReadFrom(rlk.LockedFile); err != nil { t.Fatal("Unexpected error ", err) } @@ -84,7 +82,7 @@ func TestReadFSMetadata(t *testing.T) { file.Write([]byte{'a'}) file.Close() fsMeta = fsMetaV1{} - if _, err := fsMeta.ReadFrom(sectionReader); err == nil { + if _, err := fsMeta.ReadFrom(rlk.LockedFile); err == nil { t.Fatal("Should fail", err) } } @@ -119,10 +117,9 @@ func TestWriteFSMetadata(t *testing.T) { } defer rlk.Close() - sectionReader := io.NewSectionReader(rlk, 0, rlk.Size()) // FS metadata reading, no errors expected (healthy disk) fsMeta := fsMetaV1{} - _, err = fsMeta.ReadFrom(sectionReader) + _, err = fsMeta.ReadFrom(rlk.LockedFile) if err != nil { t.Fatal("Unexpected error ", err) } diff --git a/cmd/fs-v1-multipart-common.go b/cmd/fs-v1-multipart-common.go index 940b0645e..47b63690e 100644 --- a/cmd/fs-v1-multipart-common.go +++ b/cmd/fs-v1-multipart-common.go @@ -97,7 +97,7 @@ func (fs fsObjects) deleteUploadsJSON(bucket, object, uploadID string) error { // slice is empty then we remove/purge the file. func (fs fsObjects) removeUploadID(bucket, object, uploadID string, rwlk *lock.LockedFile) error { uploadIDs := uploadsV1{} - _, err := uploadIDs.ReadFrom(io.NewSectionReader(rwlk, 0, rwlk.Size())) + _, err := uploadIDs.ReadFrom(rwlk) if err != nil { return err } @@ -121,7 +121,7 @@ func (fs fsObjects) removeUploadID(bucket, object, uploadID string, rwlk *lock.L func (fs fsObjects) addUploadID(bucket, object, uploadID string, initiated time.Time, rwlk *lock.LockedFile) error { uploadIDs := uploadsV1{} - _, err := uploadIDs.ReadFrom(io.NewSectionReader(rwlk, 0, rwlk.Size())) + _, err := uploadIDs.ReadFrom(rwlk) // For all unexpected errors, we return. if err != nil && errorCause(err) != io.EOF { return err diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index a1079f795..800cb2bb9 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -52,7 +52,7 @@ func (fs fsObjects) listMultipartUploadIDs(bucketName, objectName, uploadIDMarke // Read `uploads.json`. uploadIDs := uploadsV1{} - if _, err = uploadIDs.ReadFrom(io.NewSectionReader(rlk, 0, rlk.Size())); err != nil { + if _, err = uploadIDs.ReadFrom(rlk.LockedFile); err != nil { return nil, false, err } @@ -378,7 +378,7 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s defer rwlk.Close() fsMeta := fsMetaV1{} - _, err = fsMeta.ReadFrom(io.NewSectionReader(rwlk, 0, rwlk.Size())) + _, err = fsMeta.ReadFrom(rwlk) if err != nil { return "", toObjectErr(err, minioMetaMultipartBucket, fsMetaPath) } @@ -499,7 +499,7 @@ func (fs fsObjects) listObjectParts(bucket, object, uploadID string, partNumberM defer fs.rwPool.Close(fsMetaPath) fsMeta := fsMetaV1{} - _, err = fsMeta.ReadFrom((io.NewSectionReader(metaFile, 0, metaFile.Size()))) + _, err = fsMeta.ReadFrom(metaFile.LockedFile) if err != nil { return ListPartsInfo{}, toObjectErr(err, minioMetaBucket, fsMetaPath) } @@ -630,7 +630,7 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload fsMeta := fsMetaV1{} // Read saved fs metadata for ongoing multipart. - _, err = fsMeta.ReadFrom(io.NewSectionReader(rlk, 0, rlk.Size())) + _, err = fsMeta.ReadFrom(rlk.LockedFile) if err != nil { fs.rwPool.Close(fsMetaPathMultipart) return ObjectInfo{}, toObjectErr(err, minioMetaMultipartBucket, fsMetaPathMultipart) diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index 6db9c5635..85ced11f6 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -505,7 +505,7 @@ func (fs fsObjects) getObjectInfo(bucket, object string) (ObjectInfo, error) { if err == nil { // Read from fs metadata only if it exists. defer fs.rwPool.Close(fsMetaPath) - if _, rerr := fsMeta.ReadFrom(io.NewSectionReader(rlk, 0, rlk.Size())); rerr != nil { + if _, rerr := fsMeta.ReadFrom(rlk.LockedFile); rerr != nil { return ObjectInfo{}, toObjectErr(rerr, bucket, object) } } diff --git a/cmd/object-api-multipart-common.go b/cmd/object-api-multipart-common.go index b515d5b5e..448cca141 100644 --- a/cmd/object-api-multipart-common.go +++ b/cmd/object-api-multipart-common.go @@ -76,26 +76,30 @@ func (u *uploadsV1) IsEmpty() bool { return len(u.Uploads) == 0 } -func (u *uploadsV1) WriteTo(writer io.Writer) (n int64, err error) { +func (u *uploadsV1) WriteTo(lk *lock.LockedFile) (n int64, err error) { // Serialize to prepare to write to disk. var uplBytes []byte uplBytes, err = json.Marshal(u) if err != nil { return 0, traceError(err) } - if err = writer.(*lock.LockedFile).Truncate(0); err != nil { + if err = lk.Truncate(0); err != nil { return 0, traceError(err) } - _, err = writer.Write(uplBytes) + _, err = lk.Write(uplBytes) if err != nil { return 0, traceError(err) } return int64(len(uplBytes)), nil } -func (u *uploadsV1) ReadFrom(reader io.Reader) (n int64, err error) { +func (u *uploadsV1) ReadFrom(lk *lock.LockedFile) (n int64, err error) { var uploadIDBytes []byte - uploadIDBytes, err = ioutil.ReadAll(reader) + fi, err := lk.Stat() + if err != nil { + return 0, traceError(err) + } + uploadIDBytes, err = ioutil.ReadAll(io.NewSectionReader(lk, 0, fi.Size())) if err != nil { return 0, traceError(err) } diff --git a/pkg/lock/lock.go b/pkg/lock/lock.go index a72750fdc..f8632a667 100644 --- a/pkg/lock/lock.go +++ b/pkg/lock/lock.go @@ -89,14 +89,7 @@ func RLockedOpenFile(path string) (*RLockedFile, error) { } -// LockedFile represents a locked file, implements a helper -// method Size(), represents the size of the underlying object. +// LockedFile represents a locked file type LockedFile struct { *os.File - size int64 -} - -// Size - size of the underlying locked file. -func (l *LockedFile) Size() int64 { - return l.size } diff --git a/pkg/lock/lock_nix.go b/pkg/lock/lock_nix.go index 14263335d..537255c01 100644 --- a/pkg/lock/lock_nix.go +++ b/pkg/lock/lock_nix.go @@ -71,5 +71,5 @@ func LockedOpenFile(path string, flag int, perm os.FileMode) (*LockedFile, error } } - return &LockedFile{File: f, size: st.Size()}, nil + return &LockedFile{File: f}, nil } diff --git a/pkg/lock/lock_test.go b/pkg/lock/lock_test.go index 4c3547417..abc8e71c3 100644 --- a/pkg/lock/lock_test.go +++ b/pkg/lock/lock_test.go @@ -80,9 +80,6 @@ func TestRWLockedFile(t *testing.T) { if err != nil { t.Fatal(err) } - if rlk.Size() != 0 { - t.Fatal("File size should be zero", rlk.Size()) - } isClosed := rlk.IsClosed() if isClosed { t.Fatal("File ref count shouldn't be zero") diff --git a/pkg/lock/lock_windows.go b/pkg/lock/lock_windows.go index dcbb7ed33..04a00e093 100644 --- a/pkg/lock/lock_windows.go +++ b/pkg/lock/lock_windows.go @@ -65,7 +65,7 @@ func LockedOpenFile(path string, flag int, perm os.FileMode) (*LockedFile, error } } - return &LockedFile{File: f, size: st.Size()}, nil + return &LockedFile{File: f}, nil } func makeInheritSa() *syscall.SecurityAttributes { From c753b5dfeb5a40ef2c82b2aaa573711c1c508d60 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Thu, 26 Jan 2017 01:01:29 +0100 Subject: [PATCH 04/75] madmin: All APIs return ErrorResponse error type (#3632) Avoid returning errors.New("Got HTTP Status") in all APIs --- pkg/madmin/heal-commands.go | 12 ++++++------ pkg/madmin/lock-commands.go | 5 ++--- pkg/madmin/{service.go => service-commands.go} | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) rename pkg/madmin/{service.go => service-commands.go} (97%) diff --git a/pkg/madmin/heal-commands.go b/pkg/madmin/heal-commands.go index 09a2f791b..7544a8f89 100644 --- a/pkg/madmin/heal-commands.go +++ b/pkg/madmin/heal-commands.go @@ -19,7 +19,6 @@ package madmin import ( "encoding/xml" - "errors" "fmt" "net/http" "net/url" @@ -207,7 +206,8 @@ func (adm *AdminClient) listObjectsHeal(bucket, prefix, marker, delimiter string } if resp.StatusCode != http.StatusOK { - return toBeHealedObjects, errors.New("Got HTTP Status: " + resp.Status) + return toBeHealedObjects, httpRespToErrorResponse(resp) + } err = xml.NewDecoder(resp.Body).Decode(&toBeHealedObjects) @@ -309,7 +309,7 @@ func (adm *AdminClient) ListBucketsHeal() ([]BucketInfo, error) { } if resp.StatusCode != http.StatusOK { - return []BucketInfo{}, errors.New("Got HTTP Status: " + resp.Status) + return []BucketInfo{}, httpRespToErrorResponse(resp) } var listBucketsHealResult ListBucketsHealResponse @@ -364,7 +364,7 @@ func (adm *AdminClient) HealBucket(bucket string, dryrun bool) error { } if resp.StatusCode != http.StatusOK { - return errors.New("Got HTTP Status: " + resp.Status) + return httpRespToErrorResponse(resp) } return nil @@ -398,7 +398,7 @@ func (adm *AdminClient) HealObject(bucket, object string, dryrun bool) error { } if resp.StatusCode != http.StatusOK { - return errors.New("Got HTTP Status: " + resp.Status) + return httpRespToErrorResponse(resp) } return nil @@ -430,7 +430,7 @@ func (adm *AdminClient) HealFormat(dryrun bool) error { } if resp.StatusCode != http.StatusOK { - return errors.New("Got HTTP Status: " + resp.Status) + return httpRespToErrorResponse(resp) } return nil diff --git a/pkg/madmin/lock-commands.go b/pkg/madmin/lock-commands.go index 5b7e15cb9..7285a82d5 100644 --- a/pkg/madmin/lock-commands.go +++ b/pkg/madmin/lock-commands.go @@ -19,7 +19,6 @@ package madmin import ( "encoding/json" - "errors" "io" "io/ioutil" "net/http" @@ -118,7 +117,7 @@ func (adm *AdminClient) ListLocks(bucket, prefix string, olderThan time.Duration } if resp.StatusCode != http.StatusOK { - return nil, errors.New("Got HTTP Status: " + resp.Status) + return nil, httpRespToErrorResponse(resp) } return getLockInfos(resp.Body) @@ -150,7 +149,7 @@ func (adm *AdminClient) ClearLocks(bucket, prefix string, olderThan time.Duratio } if resp.StatusCode != http.StatusOK { - return nil, errors.New("Got HTTP Status: " + resp.Status) + return nil, httpRespToErrorResponse(resp) } return getLockInfos(resp.Body) diff --git a/pkg/madmin/service.go b/pkg/madmin/service-commands.go similarity index 97% rename from pkg/madmin/service.go rename to pkg/madmin/service-commands.go index d5c732cb1..37869cd6e 100644 --- a/pkg/madmin/service.go +++ b/pkg/madmin/service-commands.go @@ -92,7 +92,7 @@ func (adm *AdminClient) ServiceStatus() (ServiceStatusMetadata, error) { // Check response http status code if resp.StatusCode != http.StatusOK { - return ServiceStatusMetadata{}, errors.New("Got HTTP Status: " + resp.Status) + return ServiceStatusMetadata{}, httpRespToErrorResponse(resp) } // Unmarshal the server's json response @@ -129,7 +129,7 @@ func (adm *AdminClient) ServiceRestart() error { } if resp.StatusCode != http.StatusOK { - return errors.New("Got HTTP Status: " + resp.Status) + return httpRespToErrorResponse(resp) } return nil } From dafdc746053c4f79da1c20390ef242f7403bd4ef Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 26 Jan 2017 10:19:07 -0800 Subject: [PATCH 05/75] fs: if `fs.json` is empty ignore it while reading metadata. (#3634) This is needed so that we don't send wrong errors on previously failed PutObject() which would have left a stale `fs.json` entry. --- cmd/fs-v1.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index 85ced11f6..b9cdb6665 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -506,7 +506,12 @@ func (fs fsObjects) getObjectInfo(bucket, object string) (ObjectInfo, error) { // Read from fs metadata only if it exists. defer fs.rwPool.Close(fsMetaPath) if _, rerr := fsMeta.ReadFrom(rlk.LockedFile); rerr != nil { - return ObjectInfo{}, toObjectErr(rerr, bucket, object) + // `fs.json` can be empty due to previously failed + // PutObject() transaction, if we arrive at such + // a situation we just ignore and continue. + if errorCause(rerr) != io.EOF { + return ObjectInfo{}, toObjectErr(rerr, bucket, object) + } } } From cccf77229d967b0651b804b462941f75dde69d1e Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Thu, 26 Jan 2017 12:51:12 -0800 Subject: [PATCH 06/75] cleanup: Move code in *-multipart-common.go to *-multipart.go (#3638) The code in *-multipart-common.go is not common anymore. --- cmd/fs-v1-multipart-common.go | 142 --------- cmd/fs-v1-multipart-common_test.go | 49 ---- cmd/fs-v1-multipart.go | 116 ++++++++ cmd/fs-v1-multipart_test.go | 27 ++ cmd/xl-v1-multipart-common.go | 270 ------------------ cmd/xl-v1-multipart.go | 248 ++++++++++++++++ ...common_test.go => xl-v1-multipart_test.go} | 0 7 files changed, 391 insertions(+), 461 deletions(-) delete mode 100644 cmd/fs-v1-multipart-common.go delete mode 100644 cmd/fs-v1-multipart-common_test.go delete mode 100644 cmd/xl-v1-multipart-common.go rename cmd/{xl-v1-multipart-common_test.go => xl-v1-multipart_test.go} (100%) diff --git a/cmd/fs-v1-multipart-common.go b/cmd/fs-v1-multipart-common.go deleted file mode 100644 index 47b63690e..000000000 --- a/cmd/fs-v1-multipart-common.go +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2016, 2017 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 cmd - -import ( - "fmt" - "io" - "runtime" - "time" - - pathutil "path" - - "github.com/minio/minio/pkg/lock" -) - -// Returns if the prefix is a multipart upload. -func (fs fsObjects) isMultipartUpload(bucket, prefix string) bool { - uploadsIDPath := pathJoin(fs.fsPath, bucket, prefix, uploadsJSONFile) - _, err := fsStatFile(uploadsIDPath) - if err != nil { - if err == errFileNotFound { - return false - } - errorIf(err, "Unable to access uploads.json "+uploadsIDPath) - return false - } - return true -} - -// Delete uploads.json file wrapper handling a tricky case on windows. -func (fs fsObjects) deleteUploadsJSON(bucket, object, uploadID string) error { - timeID := fmt.Sprintf("%X", time.Now().UTC().UnixNano()) - tmpPath := pathJoin(fs.fsPath, minioMetaTmpBucket, fs.fsUUID, uploadID+"+"+timeID) - - multipartBucketPath := pathJoin(fs.fsPath, minioMetaMultipartBucket) - uploadPath := pathJoin(multipartBucketPath, bucket, object) - uploadsMetaPath := pathJoin(uploadPath, uploadsJSONFile) - - // Special case for windows please read through. - if runtime.GOOS == globalWindowsOSName { - // Ordinarily windows does not permit deletion or renaming of files still - // in use, but if all open handles to that file were opened with FILE_SHARE_DELETE - // then it can permit renames and deletions of open files. - // - // There are however some gotchas with this, and it is worth listing them here. - // Firstly, Windows never allows you to really delete an open file, rather it is - // flagged as delete pending and its entry in its directory remains visible - // (though no new file handles may be opened to it) and when the very last - // open handle to the file in the system is closed, only then is it truly - // deleted. Well, actually only sort of truly deleted, because Windows only - // appears to remove the file entry from the directory, but in fact that - // entry is merely hidden and actually still exists and attempting to create - // a file with the same name will return an access denied error. How long it - // silently exists for depends on a range of factors, but put it this way: - // if your code loops creating and deleting the same file name as you might - // when operating a lock file, you're going to see lots of random spurious - // access denied errors and truly dismal lock file performance compared to POSIX. - // - // We work-around these un-POSIX file semantics by taking a dual step to - // deleting files. Firstly, it renames the file to tmp location into multipartTmpBucket - // We always open files with FILE_SHARE_DELETE permission enabled, with that - // flag Windows permits renaming and deletion, and because the name was changed - // to a very random name somewhere not in its origin directory before deletion, - // you don't see those unexpected random errors when creating files with the - // same name as a recently deleted file as you do anywhere else on Windows. - // Because the file is probably not in its original containing directory any more, - // deletions of that directory will not fail with “directory not empty” as they - // otherwise normally would either. - fsRenameFile(uploadsMetaPath, tmpPath) - - // Proceed to deleting the directory. - if err := fsDeleteFile(multipartBucketPath, uploadPath); err != nil { - return err - } - - // Finally delete the renamed file. - return fsDeleteFile(pathutil.Dir(tmpPath), tmpPath) - } - return fsDeleteFile(multipartBucketPath, uploadsMetaPath) -} - -// Removes the uploadID, called either by CompleteMultipart of AbortMultipart. If the resuling uploads -// slice is empty then we remove/purge the file. -func (fs fsObjects) removeUploadID(bucket, object, uploadID string, rwlk *lock.LockedFile) error { - uploadIDs := uploadsV1{} - _, err := uploadIDs.ReadFrom(rwlk) - if err != nil { - return err - } - - // Removes upload id from the uploads list. - uploadIDs.RemoveUploadID(uploadID) - - // Check this is the last entry. - if uploadIDs.IsEmpty() { - // No more uploads left, so we delete `uploads.json` file. - return fs.deleteUploadsJSON(bucket, object, uploadID) - } // else not empty - - // Write update `uploads.json`. - _, err = uploadIDs.WriteTo(rwlk) - return err -} - -// Adds a new uploadID if no previous `uploads.json` is -// found we initialize a new one. -func (fs fsObjects) addUploadID(bucket, object, uploadID string, initiated time.Time, rwlk *lock.LockedFile) error { - uploadIDs := uploadsV1{} - - _, err := uploadIDs.ReadFrom(rwlk) - // For all unexpected errors, we return. - if err != nil && errorCause(err) != io.EOF { - return err - } - - // If we couldn't read anything, we assume a default - // (empty) upload info. - if errorCause(err) == io.EOF { - uploadIDs = newUploadsV1("fs") - } - - // Adds new upload id to the list. - uploadIDs.AddUploadID(uploadID, initiated) - - // Write update `uploads.json`. - _, err = uploadIDs.WriteTo(rwlk) - return err -} diff --git a/cmd/fs-v1-multipart-common_test.go b/cmd/fs-v1-multipart-common_test.go deleted file mode 100644 index 026799580..000000000 --- a/cmd/fs-v1-multipart-common_test.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2016 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 cmd - -import ( - "path/filepath" - "testing" -) - -// TestFSWriteUploadJSON - tests for writeUploadJSON for FS -func TestFSWriteUploadJSON(t *testing.T) { - // Prepare for tests - disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) - defer removeAll(disk) - - obj := initFSObjects(disk, t) - - bucketName := "bucket" - objectName := "object" - - obj.MakeBucket(bucketName) - _, err := obj.NewMultipartUpload(bucketName, objectName, nil) - if err != nil { - t.Fatal("Unexpected err: ", err) - } - - // newMultipartUpload will fail. - removeAll(disk) // Remove disk. - _, err = obj.NewMultipartUpload(bucketName, objectName, nil) - if err != nil { - if _, ok := errorCause(err).(BucketNotFound); !ok { - t.Fatal("Unexpected err: ", err) - } - } -} diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index 800cb2bb9..a9f55a5ea 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -24,12 +24,128 @@ import ( "io" "os" pathutil "path" + "runtime" "strings" "time" + "github.com/minio/minio/pkg/lock" "github.com/minio/sha256-simd" ) +// Returns if the prefix is a multipart upload. +func (fs fsObjects) isMultipartUpload(bucket, prefix string) bool { + uploadsIDPath := pathJoin(fs.fsPath, bucket, prefix, uploadsJSONFile) + _, err := fsStatFile(uploadsIDPath) + if err != nil { + if err == errFileNotFound { + return false + } + errorIf(err, "Unable to access uploads.json "+uploadsIDPath) + return false + } + return true +} + +// Delete uploads.json file wrapper handling a tricky case on windows. +func (fs fsObjects) deleteUploadsJSON(bucket, object, uploadID string) error { + timeID := fmt.Sprintf("%X", time.Now().UTC().UnixNano()) + tmpPath := pathJoin(fs.fsPath, minioMetaTmpBucket, fs.fsUUID, uploadID+"+"+timeID) + + multipartBucketPath := pathJoin(fs.fsPath, minioMetaMultipartBucket) + uploadPath := pathJoin(multipartBucketPath, bucket, object) + uploadsMetaPath := pathJoin(uploadPath, uploadsJSONFile) + + // Special case for windows please read through. + if runtime.GOOS == globalWindowsOSName { + // Ordinarily windows does not permit deletion or renaming of files still + // in use, but if all open handles to that file were opened with FILE_SHARE_DELETE + // then it can permit renames and deletions of open files. + // + // There are however some gotchas with this, and it is worth listing them here. + // Firstly, Windows never allows you to really delete an open file, rather it is + // flagged as delete pending and its entry in its directory remains visible + // (though no new file handles may be opened to it) and when the very last + // open handle to the file in the system is closed, only then is it truly + // deleted. Well, actually only sort of truly deleted, because Windows only + // appears to remove the file entry from the directory, but in fact that + // entry is merely hidden and actually still exists and attempting to create + // a file with the same name will return an access denied error. How long it + // silently exists for depends on a range of factors, but put it this way: + // if your code loops creating and deleting the same file name as you might + // when operating a lock file, you're going to see lots of random spurious + // access denied errors and truly dismal lock file performance compared to POSIX. + // + // We work-around these un-POSIX file semantics by taking a dual step to + // deleting files. Firstly, it renames the file to tmp location into multipartTmpBucket + // We always open files with FILE_SHARE_DELETE permission enabled, with that + // flag Windows permits renaming and deletion, and because the name was changed + // to a very random name somewhere not in its origin directory before deletion, + // you don't see those unexpected random errors when creating files with the + // same name as a recently deleted file as you do anywhere else on Windows. + // Because the file is probably not in its original containing directory any more, + // deletions of that directory will not fail with "directory not empty" as they + // otherwise normally would either. + fsRenameFile(uploadsMetaPath, tmpPath) + + // Proceed to deleting the directory. + if err := fsDeleteFile(multipartBucketPath, uploadPath); err != nil { + return err + } + + // Finally delete the renamed file. + return fsDeleteFile(pathutil.Dir(tmpPath), tmpPath) + } + return fsDeleteFile(multipartBucketPath, uploadsMetaPath) +} + +// Removes the uploadID, called either by CompleteMultipart of AbortMultipart. If the resuling uploads +// slice is empty then we remove/purge the file. +func (fs fsObjects) removeUploadID(bucket, object, uploadID string, rwlk *lock.LockedFile) error { + uploadIDs := uploadsV1{} + _, err := uploadIDs.ReadFrom(rwlk) + if err != nil { + return err + } + + // Removes upload id from the uploads list. + uploadIDs.RemoveUploadID(uploadID) + + // Check this is the last entry. + if uploadIDs.IsEmpty() { + // No more uploads left, so we delete `uploads.json` file. + return fs.deleteUploadsJSON(bucket, object, uploadID) + } // else not empty + + // Write update `uploads.json`. + _, err = uploadIDs.WriteTo(rwlk) + return err +} + +// Adds a new uploadID if no previous `uploads.json` is +// found we initialize a new one. +func (fs fsObjects) addUploadID(bucket, object, uploadID string, initiated time.Time, rwlk *lock.LockedFile) error { + uploadIDs := uploadsV1{} + + _, err := uploadIDs.ReadFrom(rwlk) + // For all unexpected errors, we return. + if err != nil && errorCause(err) != io.EOF { + return err + } + + // If we couldn't read anything, we assume a default + // (empty) upload info. + if errorCause(err) == io.EOF { + uploadIDs = newUploadsV1("fs") + } + + // Adds new upload id to the list. + uploadIDs.AddUploadID(uploadID, initiated) + + // Write update `uploads.json`. + _, err = uploadIDs.WriteTo(rwlk) + return err +} + // listMultipartUploadIDs - list all the upload ids from a marker up to 'count'. func (fs fsObjects) listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count int) ([]uploadMetadata, bool, error) { var uploads []uploadMetadata diff --git a/cmd/fs-v1-multipart_test.go b/cmd/fs-v1-multipart_test.go index ee6126fed..75ef537a5 100644 --- a/cmd/fs-v1-multipart_test.go +++ b/cmd/fs-v1-multipart_test.go @@ -22,6 +22,33 @@ import ( "testing" ) +// TestFSWriteUploadJSON - tests for writeUploadJSON for FS +func TestFSWriteUploadJSON(t *testing.T) { + // Prepare for tests + disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix()) + defer removeAll(disk) + + obj := initFSObjects(disk, t) + + bucketName := "bucket" + objectName := "object" + + obj.MakeBucket(bucketName) + _, err := obj.NewMultipartUpload(bucketName, objectName, nil) + if err != nil { + t.Fatal("Unexpected err: ", err) + } + + // newMultipartUpload will fail. + removeAll(disk) // Remove disk. + _, err = obj.NewMultipartUpload(bucketName, objectName, nil) + if err != nil { + if _, ok := errorCause(err).(BucketNotFound); !ok { + t.Fatal("Unexpected err: ", err) + } + } +} + // TestNewMultipartUploadFaultyDisk - test NewMultipartUpload with faulty disks func TestNewMultipartUploadFaultyDisk(t *testing.T) { // Prepare for tests diff --git a/cmd/xl-v1-multipart-common.go b/cmd/xl-v1-multipart-common.go deleted file mode 100644 index 1734c88b0..000000000 --- a/cmd/xl-v1-multipart-common.go +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2016 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 cmd - -import ( - "path" - "sync" - "time" -) - -// updateUploadJSON - add or remove upload ID info in all `uploads.json`. -func (xl xlObjects) updateUploadJSON(bucket, object, uploadID string, initiated time.Time, isRemove bool) error { - uploadsPath := path.Join(bucket, object, uploadsJSONFile) - tmpUploadsPath := mustGetUUID() - - // slice to store errors from disks - errs := make([]error, len(xl.storageDisks)) - // slice to store if it is a delete operation on a disk - isDelete := make([]bool, len(xl.storageDisks)) - - wg := sync.WaitGroup{} - for index, disk := range xl.storageDisks { - if disk == nil { - errs[index] = traceError(errDiskNotFound) - continue - } - // Update `uploads.json` in a go routine. - wg.Add(1) - go func(index int, disk StorageAPI) { - defer wg.Done() - - // read and parse uploads.json on this disk - uploadsJSON, err := readUploadsJSON(bucket, object, disk) - if errorCause(err) == errFileNotFound { - // If file is not found, we assume an - // default (empty) upload info. - uploadsJSON, err = newUploadsV1("xl"), nil - } - // If we have a read error, we store error and - // exit. - if err != nil { - errs[index] = err - return - } - - if !isRemove { - // Add the uploadID - uploadsJSON.AddUploadID(uploadID, initiated) - } else { - // Remove the upload ID - uploadsJSON.RemoveUploadID(uploadID) - if len(uploadsJSON.Uploads) == 0 { - isDelete[index] = true - } - } - - // For delete, rename to tmp, for the - // possibility of recovery in case of quorum - // failure. - if !isDelete[index] { - errs[index] = writeUploadJSON(&uploadsJSON, uploadsPath, tmpUploadsPath, disk) - } else { - wErr := disk.RenameFile(minioMetaMultipartBucket, uploadsPath, minioMetaTmpBucket, tmpUploadsPath) - if wErr != nil { - errs[index] = traceError(wErr) - } - - } - }(index, disk) - } - - // Wait for all the writes to finish. - wg.Wait() - - // Do we have write quorum? - if !isDiskQuorum(errs, xl.writeQuorum) { - // No quorum. Perform cleanup on the minority of disks - // on which the operation succeeded. - - // There are two cases: - // - // 1. uploads.json file was updated -> we delete the - // file that we successfully overwrote on the - // minority of disks, so that the failed quorum - // operation is not partially visible. - // - // 2. uploads.json was deleted -> in this case since - // the delete failed, we restore from tmp. - for index, disk := range xl.storageDisks { - if disk == nil || errs[index] != nil { - continue - } - wg.Add(1) - go func(index int, disk StorageAPI) { - defer wg.Done() - if !isDelete[index] { - _ = disk.DeleteFile( - minioMetaMultipartBucket, - uploadsPath, - ) - } else { - _ = disk.RenameFile( - minioMetaTmpBucket, tmpUploadsPath, - minioMetaMultipartBucket, uploadsPath, - ) - } - }(index, disk) - } - wg.Wait() - return traceError(errXLWriteQuorum) - } - - // we do have quorum, so in case of delete upload.json file - // operation, we purge from tmp. - for index, disk := range xl.storageDisks { - if disk == nil || !isDelete[index] { - continue - } - wg.Add(1) - go func(index int, disk StorageAPI) { - defer wg.Done() - // isDelete[index] = true at this point. - _ = disk.DeleteFile(minioMetaTmpBucket, tmpUploadsPath) - }(index, disk) - } - wg.Wait() - - if reducedErr := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum); reducedErr != nil { - return reducedErr - } - return nil -} - -// addUploadID - add upload ID and its initiated time to 'uploads.json'. -func (xl xlObjects) addUploadID(bucket, object string, uploadID string, initiated time.Time) error { - return xl.updateUploadJSON(bucket, object, uploadID, initiated, false) -} - -// removeUploadID - remove upload ID in 'uploads.json'. -func (xl xlObjects) removeUploadID(bucket, object string, uploadID string) error { - return xl.updateUploadJSON(bucket, object, uploadID, time.Time{}, true) -} - -// Returns if the prefix is a multipart upload. -func (xl xlObjects) isMultipartUpload(bucket, prefix string) bool { - for _, disk := range xl.getLoadBalancedDisks() { - if disk == nil { - continue - } - _, err := disk.StatFile(bucket, pathJoin(prefix, uploadsJSONFile)) - if err == nil { - return true - } - // For any reason disk was deleted or goes offline, continue - if isErrIgnored(err, objMetadataOpIgnoredErrs...) { - continue - } - break - } - return false -} - -// isUploadIDExists - verify if a given uploadID exists and is valid. -func (xl xlObjects) isUploadIDExists(bucket, object, uploadID string) bool { - uploadIDPath := path.Join(bucket, object, uploadID) - return xl.isObject(minioMetaMultipartBucket, uploadIDPath) -} - -// Removes part given by partName belonging to a mulitpart upload from minioMetaBucket -func (xl xlObjects) removeObjectPart(bucket, object, uploadID, partName string) { - curpartPath := path.Join(bucket, object, uploadID, partName) - wg := sync.WaitGroup{} - for i, disk := range xl.storageDisks { - if disk == nil { - continue - } - wg.Add(1) - go func(index int, disk StorageAPI) { - defer wg.Done() - // Ignoring failure to remove parts that weren't present in CompleteMultipartUpload - // requests. xl.json is the authoritative source of truth on which parts constitute - // the object. The presence of parts that don't belong in the object doesn't affect correctness. - _ = disk.DeleteFile(minioMetaMultipartBucket, curpartPath) - }(i, disk) - } - wg.Wait() -} - -// statPart - returns fileInfo structure for a successful stat on part file. -func (xl xlObjects) statPart(bucket, object, uploadID, partName string) (fileInfo FileInfo, err error) { - partNamePath := path.Join(bucket, object, uploadID, partName) - for _, disk := range xl.getLoadBalancedDisks() { - if disk == nil { - continue - } - fileInfo, err = disk.StatFile(minioMetaMultipartBucket, partNamePath) - if err == nil { - return fileInfo, nil - } - err = traceError(err) - // For any reason disk was deleted or goes offline we continue to next disk. - if isErrIgnored(err, objMetadataOpIgnoredErrs...) { - continue - } - - // Catastrophic error, we return. - break - } - return FileInfo{}, err -} - -// commitXLMetadata - commit `xl.json` from source prefix to destination prefix in the given slice of disks. -func commitXLMetadata(disks []StorageAPI, srcBucket, srcPrefix, dstBucket, dstPrefix string, quorum int) error { - var wg = &sync.WaitGroup{} - var mErrs = make([]error, len(disks)) - - srcJSONFile := path.Join(srcPrefix, xlMetaJSONFile) - dstJSONFile := path.Join(dstPrefix, xlMetaJSONFile) - - // Rename `xl.json` to all disks in parallel. - for index, disk := range disks { - if disk == nil { - mErrs[index] = traceError(errDiskNotFound) - continue - } - wg.Add(1) - // Rename `xl.json` in a routine. - go func(index int, disk StorageAPI) { - defer wg.Done() - // Delete any dangling directories. - defer disk.DeleteFile(srcBucket, srcPrefix) - - // Renames `xl.json` from source prefix to destination prefix. - rErr := disk.RenameFile(srcBucket, srcJSONFile, dstBucket, dstJSONFile) - if rErr != nil { - mErrs[index] = traceError(rErr) - return - } - mErrs[index] = nil - }(index, disk) - } - // Wait for all the routines. - wg.Wait() - - // Do we have write Quorum?. - if !isDiskQuorum(mErrs, quorum) { - // Delete all `xl.json` successfully renamed. - deleteAllXLMetadata(disks, dstBucket, dstPrefix, mErrs) - return traceError(errXLWriteQuorum) - } - - if reducedErr := reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, quorum); reducedErr != nil { - return reducedErr - } - return nil -} diff --git a/cmd/xl-v1-multipart.go b/cmd/xl-v1-multipart.go index 58f421121..92fafc35e 100644 --- a/cmd/xl-v1-multipart.go +++ b/cmd/xl-v1-multipart.go @@ -25,12 +25,260 @@ import ( "io/ioutil" "path" "strings" + "sync" "time" "github.com/minio/minio/pkg/mimedb" "github.com/minio/sha256-simd" ) +// updateUploadJSON - add or remove upload ID info in all `uploads.json`. +func (xl xlObjects) updateUploadJSON(bucket, object, uploadID string, initiated time.Time, isRemove bool) error { + uploadsPath := path.Join(bucket, object, uploadsJSONFile) + tmpUploadsPath := mustGetUUID() + + // slice to store errors from disks + errs := make([]error, len(xl.storageDisks)) + // slice to store if it is a delete operation on a disk + isDelete := make([]bool, len(xl.storageDisks)) + + wg := sync.WaitGroup{} + for index, disk := range xl.storageDisks { + if disk == nil { + errs[index] = traceError(errDiskNotFound) + continue + } + // Update `uploads.json` in a go routine. + wg.Add(1) + go func(index int, disk StorageAPI) { + defer wg.Done() + + // read and parse uploads.json on this disk + uploadsJSON, err := readUploadsJSON(bucket, object, disk) + if errorCause(err) == errFileNotFound { + // If file is not found, we assume an + // default (empty) upload info. + uploadsJSON, err = newUploadsV1("xl"), nil + } + // If we have a read error, we store error and + // exit. + if err != nil { + errs[index] = err + return + } + + if !isRemove { + // Add the uploadID + uploadsJSON.AddUploadID(uploadID, initiated) + } else { + // Remove the upload ID + uploadsJSON.RemoveUploadID(uploadID) + if len(uploadsJSON.Uploads) == 0 { + isDelete[index] = true + } + } + + // For delete, rename to tmp, for the + // possibility of recovery in case of quorum + // failure. + if !isDelete[index] { + errs[index] = writeUploadJSON(&uploadsJSON, uploadsPath, tmpUploadsPath, disk) + } else { + wErr := disk.RenameFile(minioMetaMultipartBucket, uploadsPath, minioMetaTmpBucket, tmpUploadsPath) + if wErr != nil { + errs[index] = traceError(wErr) + } + + } + }(index, disk) + } + + // Wait for all the writes to finish. + wg.Wait() + + // Do we have write quorum? + if !isDiskQuorum(errs, xl.writeQuorum) { + // No quorum. Perform cleanup on the minority of disks + // on which the operation succeeded. + + // There are two cases: + // + // 1. uploads.json file was updated -> we delete the + // file that we successfully overwrote on the + // minority of disks, so that the failed quorum + // operation is not partially visible. + // + // 2. uploads.json was deleted -> in this case since + // the delete failed, we restore from tmp. + for index, disk := range xl.storageDisks { + if disk == nil || errs[index] != nil { + continue + } + wg.Add(1) + go func(index int, disk StorageAPI) { + defer wg.Done() + if !isDelete[index] { + _ = disk.DeleteFile( + minioMetaMultipartBucket, + uploadsPath, + ) + } else { + _ = disk.RenameFile( + minioMetaTmpBucket, tmpUploadsPath, + minioMetaMultipartBucket, uploadsPath, + ) + } + }(index, disk) + } + wg.Wait() + return traceError(errXLWriteQuorum) + } + + // we do have quorum, so in case of delete upload.json file + // operation, we purge from tmp. + for index, disk := range xl.storageDisks { + if disk == nil || !isDelete[index] { + continue + } + wg.Add(1) + go func(index int, disk StorageAPI) { + defer wg.Done() + // isDelete[index] = true at this point. + _ = disk.DeleteFile(minioMetaTmpBucket, tmpUploadsPath) + }(index, disk) + } + wg.Wait() + + if reducedErr := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum); reducedErr != nil { + return reducedErr + } + return nil +} + +// addUploadID - add upload ID and its initiated time to 'uploads.json'. +func (xl xlObjects) addUploadID(bucket, object string, uploadID string, initiated time.Time) error { + return xl.updateUploadJSON(bucket, object, uploadID, initiated, false) +} + +// removeUploadID - remove upload ID in 'uploads.json'. +func (xl xlObjects) removeUploadID(bucket, object string, uploadID string) error { + return xl.updateUploadJSON(bucket, object, uploadID, time.Time{}, true) +} + +// Returns if the prefix is a multipart upload. +func (xl xlObjects) isMultipartUpload(bucket, prefix string) bool { + for _, disk := range xl.getLoadBalancedDisks() { + if disk == nil { + continue + } + _, err := disk.StatFile(bucket, pathJoin(prefix, uploadsJSONFile)) + if err == nil { + return true + } + // For any reason disk was deleted or goes offline, continue + if isErrIgnored(err, objMetadataOpIgnoredErrs...) { + continue + } + break + } + return false +} + +// isUploadIDExists - verify if a given uploadID exists and is valid. +func (xl xlObjects) isUploadIDExists(bucket, object, uploadID string) bool { + uploadIDPath := path.Join(bucket, object, uploadID) + return xl.isObject(minioMetaMultipartBucket, uploadIDPath) +} + +// Removes part given by partName belonging to a mulitpart upload from minioMetaBucket +func (xl xlObjects) removeObjectPart(bucket, object, uploadID, partName string) { + curpartPath := path.Join(bucket, object, uploadID, partName) + wg := sync.WaitGroup{} + for i, disk := range xl.storageDisks { + if disk == nil { + continue + } + wg.Add(1) + go func(index int, disk StorageAPI) { + defer wg.Done() + // Ignoring failure to remove parts that weren't present in CompleteMultipartUpload + // requests. xl.json is the authoritative source of truth on which parts constitute + // the object. The presence of parts that don't belong in the object doesn't affect correctness. + _ = disk.DeleteFile(minioMetaMultipartBucket, curpartPath) + }(i, disk) + } + wg.Wait() +} + +// statPart - returns fileInfo structure for a successful stat on part file. +func (xl xlObjects) statPart(bucket, object, uploadID, partName string) (fileInfo FileInfo, err error) { + partNamePath := path.Join(bucket, object, uploadID, partName) + for _, disk := range xl.getLoadBalancedDisks() { + if disk == nil { + continue + } + fileInfo, err = disk.StatFile(minioMetaMultipartBucket, partNamePath) + if err == nil { + return fileInfo, nil + } + err = traceError(err) + // For any reason disk was deleted or goes offline we continue to next disk. + if isErrIgnored(err, objMetadataOpIgnoredErrs...) { + continue + } + + // Catastrophic error, we return. + break + } + return FileInfo{}, err +} + +// commitXLMetadata - commit `xl.json` from source prefix to destination prefix in the given slice of disks. +func commitXLMetadata(disks []StorageAPI, srcBucket, srcPrefix, dstBucket, dstPrefix string, quorum int) error { + var wg = &sync.WaitGroup{} + var mErrs = make([]error, len(disks)) + + srcJSONFile := path.Join(srcPrefix, xlMetaJSONFile) + dstJSONFile := path.Join(dstPrefix, xlMetaJSONFile) + + // Rename `xl.json` to all disks in parallel. + for index, disk := range disks { + if disk == nil { + mErrs[index] = traceError(errDiskNotFound) + continue + } + wg.Add(1) + // Rename `xl.json` in a routine. + go func(index int, disk StorageAPI) { + defer wg.Done() + // Delete any dangling directories. + defer disk.DeleteFile(srcBucket, srcPrefix) + + // Renames `xl.json` from source prefix to destination prefix. + rErr := disk.RenameFile(srcBucket, srcJSONFile, dstBucket, dstJSONFile) + if rErr != nil { + mErrs[index] = traceError(rErr) + return + } + mErrs[index] = nil + }(index, disk) + } + // Wait for all the routines. + wg.Wait() + + // Do we have write Quorum?. + if !isDiskQuorum(mErrs, quorum) { + // Delete all `xl.json` successfully renamed. + deleteAllXLMetadata(disks, dstBucket, dstPrefix, mErrs) + return traceError(errXLWriteQuorum) + } + + if reducedErr := reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, quorum); reducedErr != nil { + return reducedErr + } + return nil +} + // listMultipartUploads - lists all multipart uploads. func (xl xlObjects) listMultipartUploads(bucket, prefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (ListMultipartsInfo, error) { result := ListMultipartsInfo{ diff --git a/cmd/xl-v1-multipart-common_test.go b/cmd/xl-v1-multipart_test.go similarity index 100% rename from cmd/xl-v1-multipart-common_test.go rename to cmd/xl-v1-multipart_test.go From 8e49a3d04718de76b6e3062318ccffc787d553fe Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Fri, 27 Jan 2017 00:22:41 +0100 Subject: [PATCH 07/75] Simplify running cmd.Main() for external tests (#3636) An external test that runs cmd.Main() has a difficulty to set cmd arguments and MINIO_{ACCESS,SECRET}_KEY values, this commit changes a little the current behavior in a way that helps external tests. --- cmd/globals.go | 8 ++++---- cmd/main.go | 8 ++++++-- main.go | 8 ++++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/cmd/globals.go b/cmd/globals.go index e1b943b27..eaa0508e5 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -110,11 +110,11 @@ var ( // Minio server user agent string. globalServerUserAgent = "Minio/" + ReleaseTag + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")" - // Access key passed from the environment - globalEnvAccessKey = os.Getenv("MINIO_ACCESS_KEY") + // Global server's access key + globalEnvAccessKey = "" - // Secret key passed from the environment - globalEnvSecretKey = os.Getenv("MINIO_SECRET_KEY") + // Global server's secret key + globalEnvSecretKey = "" // url.URL endpoints of disks that belong to the object storage. globalEndpoints = []*url.URL{} diff --git a/cmd/main.go b/cmd/main.go index db214201e..0038042ea 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -190,6 +190,8 @@ func minioInit(ctx *cli.Context) { enableLoggers() // Fetch access keys from environment variables and update the config. + globalEnvAccessKey = os.Getenv("MINIO_ACCESS_KEY") + globalEnvSecretKey = os.Getenv("MINIO_SECRET_KEY") if globalEnvAccessKey != "" && globalEnvSecretKey != "" { // Set new credentials. serverConfig.SetCredential(credential{ @@ -210,7 +212,7 @@ func minioInit(ctx *cli.Context) { } // Main main for minio server. -func Main() { +func Main(args []string, exitFn func(int)) { app := registerApp() app.Before = func(c *cli.Context) error { // Valid input arguments to main. @@ -224,5 +226,7 @@ func Main() { } // Run the app - exit on error. - app.RunAndExitOnError() + if err := app.Run(args); err != nil { + exitFn(1) + } } diff --git a/main.go b/main.go index 03814d857..7c635a6b7 100644 --- a/main.go +++ b/main.go @@ -22,8 +22,12 @@ package main // import "github.com/minio/minio" -import minio "github.com/minio/minio/cmd" +import ( + "os" + + minio "github.com/minio/minio/cmd" +) func main() { - minio.Main() + minio.Main(os.Args, os.Exit) } From 17dd1c19df40a173fb171a25a122fb7ea78da413 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Thu, 26 Jan 2017 15:39:22 -0800 Subject: [PATCH 08/75] cleanup: refactor common code between FS and XL listDirFactory. (#3639) --- cmd/fs-v1.go | 36 +++------------------- cmd/tree-walk.go | 65 +++++++++++++-------------------------- cmd/xl-v1-list-objects.go | 28 +++++++++++++++++ 3 files changed, 54 insertions(+), 75 deletions(-) diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index b9cdb6665..2a455089f 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -731,37 +731,11 @@ func (fs fsObjects) listDirFactory(isLeaf isLeafFunc) listDirFunc { // listDir - lists all the entries at a given prefix and given entry in the prefix. listDir := func(bucket, prefixDir, prefixEntry string) (entries []string, delayIsLeaf bool, err error) { entries, err = readDir(pathJoin(fs.fsPath, bucket, prefixDir)) - if err == nil { - // Listing needs to be sorted. - sort.Strings(entries) - - // Filter entries that have the prefix prefixEntry. - entries = filterMatchingPrefix(entries, prefixEntry) - - // Can isLeaf() check be delayed till when it has to be sent down the - // treeWalkResult channel? - delayIsLeaf = delayIsLeafCheck(entries) - if delayIsLeaf { - return entries, delayIsLeaf, nil - } - - // isLeaf() check has to happen here so that trailing "/" for objects can be removed. - for i, entry := range entries { - if isLeaf(bucket, pathJoin(prefixDir, entry)) { - entries[i] = strings.TrimSuffix(entry, slashSeparator) - } - } - - // Sort again after removing trailing "/" for objects as the previous sort - // does not hold good anymore. - sort.Strings(entries) - - // Succes. - return entries, delayIsLeaf, nil - } // Return error at the end. - - // Error. - return nil, false, err + if err != nil { + return nil, false, err + } + entries, delayIsLeaf = filterListEntries(bucket, prefixDir, entries, prefixEntry, isLeaf) + return entries, delayIsLeaf, nil } // Return list factory instance. diff --git a/cmd/tree-walk.go b/cmd/tree-walk.go index 92cfb8578..8993a96d0 100644 --- a/cmd/tree-walk.go +++ b/cmd/tree-walk.go @@ -95,53 +95,30 @@ type listDirFunc func(bucket, prefixDir, prefixEntry string) (entries []string, // 4. XL backend multipart listing - isLeaf is true if the entry is a directory and contains uploads.json type isLeafFunc func(string, string) bool -// Returns function "listDir" of the type listDirFunc. -// isLeaf - is used by listDir function to check if an entry is a leaf or non-leaf entry. -// disks - used for doing disk.ListDir(). FS passes single disk argument, XL passes a list of disks. -func listDirFactory(isLeaf isLeafFunc, treeWalkIgnoredErrs []error, disks ...StorageAPI) listDirFunc { - // listDir - lists all the entries at a given prefix and given entry in the prefix. - listDir := func(bucket, prefixDir, prefixEntry string) (entries []string, delayIsLeaf bool, err error) { - for _, disk := range disks { - if disk == nil { - continue - } - entries, err = disk.ListDir(bucket, prefixDir) - if err == nil { - // Listing needs to be sorted. - sort.Strings(entries) +func filterListEntries(bucket, prefixDir string, entries []string, prefixEntry string, isLeaf isLeafFunc) ([]string, bool) { + // Listing needs to be sorted. + sort.Strings(entries) - // Filter entries that have the prefix prefixEntry. - entries = filterMatchingPrefix(entries, prefixEntry) + // Filter entries that have the prefix prefixEntry. + entries = filterMatchingPrefix(entries, prefixEntry) - // Can isLeaf() check be delayed till when it has to be sent down the - // treeWalkResult channel? - delayIsLeaf = delayIsLeafCheck(entries) - if delayIsLeaf { - return entries, delayIsLeaf, nil - } - - // isLeaf() check has to happen here so that trailing "/" for objects can be removed. - for i, entry := range entries { - if isLeaf(bucket, pathJoin(prefixDir, entry)) { - entries[i] = strings.TrimSuffix(entry, slashSeparator) - } - } - // Sort again after removing trailing "/" for objects as the previous sort - // does not hold good anymore. - sort.Strings(entries) - return entries, delayIsLeaf, nil - } - // For any reason disk was deleted or goes offline, continue - // and list from other disks if possible. - if isErrIgnored(err, treeWalkIgnoredErrs...) { - continue - } - break - } - // Return error at the end. - return nil, false, traceError(err) + // Can isLeaf() check be delayed till when it has to be sent down the + // treeWalkResult channel? + delayIsLeaf := delayIsLeafCheck(entries) + if delayIsLeaf { + return entries, true } - return listDir + + // isLeaf() check has to happen here so that trailing "/" for objects can be removed. + for i, entry := range entries { + if isLeaf(bucket, pathJoin(prefixDir, entry)) { + entries[i] = strings.TrimSuffix(entry, slashSeparator) + } + } + // Sort again after removing trailing "/" for objects as the previous sort + // does not hold good anymore. + sort.Strings(entries) + return entries, false } // treeWalk walks directory tree recursively pushing treeWalkResult into the channel as and when it encounters files. diff --git a/cmd/xl-v1-list-objects.go b/cmd/xl-v1-list-objects.go index 477c25768..b9fff36ee 100644 --- a/cmd/xl-v1-list-objects.go +++ b/cmd/xl-v1-list-objects.go @@ -18,6 +18,34 @@ package cmd import "strings" +// Returns function "listDir" of the type listDirFunc. +// isLeaf - is used by listDir function to check if an entry is a leaf or non-leaf entry. +// disks - used for doing disk.ListDir(). FS passes single disk argument, XL passes a list of disks. +func listDirFactory(isLeaf isLeafFunc, treeWalkIgnoredErrs []error, disks ...StorageAPI) listDirFunc { + // listDir - lists all the entries at a given prefix and given entry in the prefix. + listDir := func(bucket, prefixDir, prefixEntry string) (entries []string, delayIsLeaf bool, err error) { + for _, disk := range disks { + if disk == nil { + continue + } + entries, err = disk.ListDir(bucket, prefixDir) + if err == nil { + entries, delayIsLeaf = filterListEntries(bucket, prefixDir, entries, prefixEntry, isLeaf) + return entries, delayIsLeaf, nil + } + // For any reason disk was deleted or goes offline, continue + // and list from other disks if possible. + if isErrIgnored(err, treeWalkIgnoredErrs...) { + continue + } + break + } + // Return error at the end. + return nil, false, traceError(err) + } + return listDir +} + // listObjects - wrapper function implemented over file tree walk. func (xl xlObjects) listObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, error) { // Default is recursive, if delimiter is set then list non recursive. From 152cdf1c0546c2744a8605e843ea4bc72e3728c9 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Thu, 26 Jan 2017 15:40:10 -0800 Subject: [PATCH 09/75] fs: Move traceError() to lower functions where possible. (#3633) --- cmd/fs-v1-helpers.go | 128 +++++++++++++++++++------------------- cmd/fs-v1-helpers_test.go | 30 ++++----- cmd/fs-v1-multipart.go | 8 +-- cmd/fs-v1.go | 32 +++++----- 4 files changed, 100 insertions(+), 98 deletions(-) diff --git a/cmd/fs-v1-helpers.go b/cmd/fs-v1-helpers.go index 4c911380c..a64ad4c71 100644 --- a/cmd/fs-v1-helpers.go +++ b/cmd/fs-v1-helpers.go @@ -27,20 +27,20 @@ import ( // windows automatically. func fsRemoveFile(filePath string) (err error) { if filePath == "" { - return errInvalidArgument + return traceError(errInvalidArgument) } if err = checkPathLength(filePath); err != nil { - return err + return traceError(err) } if err = os.Remove(preparePath(filePath)); err != nil { if os.IsNotExist(err) { - return errFileNotFound + return traceError(errFileNotFound) } else if os.IsPermission(err) { - return errFileAccessDenied + return traceError(errFileAccessDenied) } - return err + return traceError(err) } return nil @@ -50,43 +50,44 @@ func fsRemoveFile(filePath string) (err error) { // long paths for windows automatically. func fsRemoveAll(dirPath string) (err error) { if dirPath == "" { - return errInvalidArgument + return traceError(errInvalidArgument) } if err = checkPathLength(dirPath); err != nil { - return err + return traceError(err) } if err = removeAll(dirPath); err != nil { if os.IsPermission(err) { - return errVolumeAccessDenied + return traceError(errVolumeAccessDenied) } + return traceError(err) } - return err - + return nil } // Removes a directory only if its empty, handles long // paths for windows automatically. func fsRemoveDir(dirPath string) (err error) { if dirPath == "" { - return errInvalidArgument + return traceError(errInvalidArgument) } if err = checkPathLength(dirPath); err != nil { - return err + return traceError(err) } if err = os.Remove(preparePath(dirPath)); err != nil { if os.IsNotExist(err) { - return errVolumeNotFound + return traceError(errVolumeNotFound) } else if isSysErrNotEmpty(err) { - return errVolumeNotEmpty + return traceError(errVolumeNotEmpty) } + return traceError(err) } - return err + return nil } // Creates a new directory, parent dir should exist @@ -95,26 +96,27 @@ func fsRemoveDir(dirPath string) (err error) { // are handled automatically. func fsMkdir(dirPath string) (err error) { if dirPath == "" { - return errInvalidArgument + return traceError(errInvalidArgument) } if err = checkPathLength(dirPath); err != nil { - return err + return traceError(err) } if err = os.Mkdir(preparePath(dirPath), 0777); err != nil { if os.IsExist(err) { - return errVolumeExists + return traceError(errVolumeExists) } else if os.IsPermission(err) { - return errDiskAccessDenied + return traceError(errDiskAccessDenied) } else if isSysErrNotDir(err) { // File path cannot be verified since // one of the parents is a file. - return errDiskAccessDenied + return traceError(errDiskAccessDenied) } else if isSysErrPathNotFound(err) { // Add specific case for windows. - return errDiskAccessDenied + return traceError(errDiskAccessDenied) } + return traceError(err) } return nil @@ -124,24 +126,24 @@ func fsMkdir(dirPath string) (err error) { // attributes upon success. func fsStatDir(statDir string) (os.FileInfo, error) { if statDir == "" { - return nil, errInvalidArgument + return nil, traceError(errInvalidArgument) } if err := checkPathLength(statDir); err != nil { - return nil, err + return nil, traceError(err) } fi, err := os.Stat(preparePath(statDir)) if err != nil { if os.IsNotExist(err) { - return nil, errVolumeNotFound + return nil, traceError(errVolumeNotFound) } else if os.IsPermission(err) { - return nil, errVolumeAccessDenied + return nil, traceError(errVolumeAccessDenied) } - return nil, err + return nil, traceError(err) } if !fi.IsDir() { - return nil, errVolumeAccessDenied + return nil, traceError(errVolumeAccessDenied) } return fi, nil @@ -150,28 +152,28 @@ func fsStatDir(statDir string) (os.FileInfo, error) { // Lookup if file exists, returns file attributes upon success func fsStatFile(statFile string) (os.FileInfo, error) { if statFile == "" { - return nil, errInvalidArgument + return nil, traceError(errInvalidArgument) } if err := checkPathLength(statFile); err != nil { - return nil, err + return nil, traceError(err) } fi, err := os.Stat(preparePath(statFile)) if err != nil { if os.IsNotExist(err) { - return nil, errFileNotFound + return nil, traceError(errFileNotFound) } else if os.IsPermission(err) { - return nil, errFileAccessDenied + return nil, traceError(errFileAccessDenied) } else if isSysErrNotDir(err) { - return nil, errFileAccessDenied + return nil, traceError(errFileAccessDenied) } else if isSysErrPathNotFound(err) { - return nil, errFileNotFound + return nil, traceError(errFileNotFound) } - return nil, err + return nil, traceError(err) } if fi.IsDir() { - return nil, errFileNotFound + return nil, traceError(errFileNotFound) } return fi, nil } @@ -180,44 +182,44 @@ func fsStatFile(statFile string) (os.FileInfo, error) { // a readable stream and the size of the readable stream. func fsOpenFile(readPath string, offset int64) (io.ReadCloser, int64, error) { if readPath == "" || offset < 0 { - return nil, 0, errInvalidArgument + return nil, 0, traceError(errInvalidArgument) } if err := checkPathLength(readPath); err != nil { - return nil, 0, err + return nil, 0, traceError(err) } fr, err := os.Open(preparePath(readPath)) if err != nil { if os.IsNotExist(err) { - return nil, 0, errFileNotFound + return nil, 0, traceError(errFileNotFound) } else if os.IsPermission(err) { - return nil, 0, errFileAccessDenied + return nil, 0, traceError(errFileAccessDenied) } else if isSysErrNotDir(err) { // File path cannot be verified since one of the parents is a file. - return nil, 0, errFileAccessDenied + return nil, 0, traceError(errFileAccessDenied) } else if isSysErrPathNotFound(err) { // Add specific case for windows. - return nil, 0, errFileNotFound + return nil, 0, traceError(errFileNotFound) } - return nil, 0, err + return nil, 0, traceError(err) } // Stat to get the size of the file at path. st, err := fr.Stat() if err != nil { - return nil, 0, err + return nil, 0, traceError(err) } // Verify if its not a regular file, since subsequent Seek is undefined. if !st.Mode().IsRegular() { - return nil, 0, errIsNotRegular + return nil, 0, traceError(errIsNotRegular) } // Seek to the requested offset. if offset > 0 { _, err = fr.Seek(offset, os.SEEK_SET) if err != nil { - return nil, 0, err + return nil, 0, traceError(err) } } @@ -228,22 +230,22 @@ func fsOpenFile(readPath string, offset int64) (io.ReadCloser, int64, error) { // Creates a file and copies data from incoming reader. Staging buffer is used by io.CopyBuffer. func fsCreateFile(tempObjPath string, reader io.Reader, buf []byte, fallocSize int64) (int64, error) { if tempObjPath == "" || reader == nil || buf == nil { - return 0, errInvalidArgument + return 0, traceError(errInvalidArgument) } if err := checkPathLength(tempObjPath); err != nil { - return 0, err + return 0, traceError(err) } if err := mkdirAll(pathutil.Dir(tempObjPath), 0777); err != nil { - return 0, err + return 0, traceError(err) } writer, err := os.OpenFile(preparePath(tempObjPath), os.O_CREATE|os.O_WRONLY, 0666) if err != nil { // File path cannot be verified since one of the parents is a file. if isSysErrNotDir(err) { - return 0, errFileAccessDenied + return 0, traceError(errFileAccessDenied) } return 0, err } @@ -252,13 +254,13 @@ func fsCreateFile(tempObjPath string, reader io.Reader, buf []byte, fallocSize i // Fallocate only if the size is final object is known. if fallocSize > 0 { if err = fsFAllocate(int(writer.Fd()), 0, fallocSize); err != nil { - return 0, err + return 0, traceError(err) } } bytesWritten, err := io.CopyBuffer(writer, reader, buf) if err != nil { - return 0, err + return 0, traceError(err) } return bytesWritten, nil @@ -267,20 +269,20 @@ func fsCreateFile(tempObjPath string, reader io.Reader, buf []byte, fallocSize i // Removes uploadID at destination path. func fsRemoveUploadIDPath(basePath, uploadIDPath string) error { if basePath == "" || uploadIDPath == "" { - return errInvalidArgument + return traceError(errInvalidArgument) } // List all the entries in uploadID. entries, err := readDir(uploadIDPath) if err != nil && err != errFileNotFound { - return err + return traceError(err) } // Delete all the entries obtained from previous readdir. for _, entryPath := range entries { err = fsDeleteFile(basePath, pathJoin(uploadIDPath, entryPath)) if err != nil && err != errFileNotFound { - return err + return traceError(err) } } @@ -325,11 +327,11 @@ func fsRenameFile(sourcePath, destPath string) error { // this function additionally protects the basePath from being deleted. func fsDeleteFile(basePath, deletePath string) error { if err := checkPathLength(basePath); err != nil { - return err + return traceError(err) } if err := checkPathLength(deletePath); err != nil { - return err + return traceError(err) } if basePath == deletePath { @@ -340,11 +342,11 @@ func fsDeleteFile(basePath, deletePath string) error { pathSt, err := os.Stat(preparePath(deletePath)) if err != nil { if os.IsNotExist(err) { - return errFileNotFound + return traceError(errFileNotFound) } else if os.IsPermission(err) { - return errFileAccessDenied + return traceError(errFileAccessDenied) } - return err + return traceError(err) } if pathSt.IsDir() && !isDirEmpty(deletePath) { @@ -355,13 +357,13 @@ func fsDeleteFile(basePath, deletePath string) error { // Attempt to remove path. if err = os.Remove(preparePath(deletePath)); err != nil { if os.IsNotExist(err) { - return errFileNotFound + return traceError(errFileNotFound) } else if os.IsPermission(err) { - return errFileAccessDenied + return traceError(errFileAccessDenied) } else if isSysErrNotEmpty(err) { - return errVolumeNotEmpty + return traceError(errVolumeNotEmpty) } - return err + return traceError(err) } // Recursively go down the next path and delete again. diff --git a/cmd/fs-v1-helpers_test.go b/cmd/fs-v1-helpers_test.go index 67541f670..afaff8a80 100644 --- a/cmd/fs-v1-helpers_test.go +++ b/cmd/fs-v1-helpers_test.go @@ -31,11 +31,11 @@ func TestFSStats(t *testing.T) { // Setup test environment. - if err = fsMkdir(""); err != errInvalidArgument { + if err = fsMkdir(""); errorCause(err) != errInvalidArgument { t.Fatal("Unexpected error", err) } - if err = fsMkdir(pathJoin(path, "my-obj-del-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")); err != errFileNameTooLong { + if err = fsMkdir(pathJoin(path, "my-obj-del-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")); errorCause(err) != errFileNameTooLong { t.Fatal("Unexpected error", err) } @@ -51,7 +51,7 @@ func TestFSStats(t *testing.T) { // Seek back. reader.Seek(0, 0) - if err = fsMkdir(pathJoin(path, "success-vol", "success-file")); err != errVolumeExists { + if err = fsMkdir(pathJoin(path, "success-vol", "success-file")); errorCause(err) != errVolumeExists { t.Fatal("Unexpected error", err) } @@ -138,11 +138,11 @@ func TestFSStats(t *testing.T) { for i, testCase := range testCases { if testCase.srcPath != "" { - if _, err := fsStatFile(pathJoin(testCase.srcFSPath, testCase.srcVol, testCase.srcPath)); err != testCase.expectedErr { + if _, err := fsStatFile(pathJoin(testCase.srcFSPath, testCase.srcVol, testCase.srcPath)); errorCause(err) != testCase.expectedErr { t.Fatalf("TestPosix case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err) } } else { - if _, err := fsStatDir(pathJoin(testCase.srcFSPath, testCase.srcVol)); err != testCase.expectedErr { + if _, err := fsStatDir(pathJoin(testCase.srcFSPath, testCase.srcVol)); errorCause(err) != testCase.expectedErr { t.Fatalf("TestPosix case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err) } } @@ -161,11 +161,11 @@ func TestFSCreateAndOpen(t *testing.T) { t.Fatalf("Unable to create directory, %s", err) } - if _, err = fsCreateFile("", nil, nil, 0); err != errInvalidArgument { + if _, err = fsCreateFile("", nil, nil, 0); errorCause(err) != errInvalidArgument { t.Fatal("Unexpected error", err) } - if _, _, err = fsOpenFile("", -1); err != errInvalidArgument { + if _, _, err = fsOpenFile("", -1); errorCause(err) != errInvalidArgument { t.Fatal("Unexpected error", err) } @@ -200,17 +200,17 @@ func TestFSCreateAndOpen(t *testing.T) { for i, testCase := range testCases { _, err = fsCreateFile(pathJoin(path, testCase.srcVol, testCase.srcPath), reader, buf, reader.Size()) - if err != testCase.expectedErr { + if errorCause(err) != testCase.expectedErr { t.Errorf("Test case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err) } _, _, err = fsOpenFile(pathJoin(path, testCase.srcVol, testCase.srcPath), 0) - if err != testCase.expectedErr { + if errorCause(err) != testCase.expectedErr { t.Errorf("Test case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err) } } // Attempt to open a directory. - if _, _, err = fsOpenFile(pathJoin(path), 0); err != errIsNotRegular { + if _, _, err = fsOpenFile(pathJoin(path), 0); errorCause(err) != errIsNotRegular { t.Fatal("Unexpected error", err) } } @@ -272,7 +272,7 @@ func TestFSDeletes(t *testing.T) { } for i, testCase := range testCases { - if err = fsDeleteFile(path, pathJoin(path, testCase.srcVol, testCase.srcPath)); err != testCase.expectedErr { + if err = fsDeleteFile(path, pathJoin(path, testCase.srcVol, testCase.srcPath)); errorCause(err) != testCase.expectedErr { t.Errorf("Test case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err) } } @@ -374,11 +374,11 @@ func TestFSRemoves(t *testing.T) { for i, testCase := range testCases { if testCase.srcPath != "" { - if err = fsRemoveFile(pathJoin(testCase.srcFSPath, testCase.srcVol, testCase.srcPath)); err != testCase.expectedErr { + if err = fsRemoveFile(pathJoin(testCase.srcFSPath, testCase.srcVol, testCase.srcPath)); errorCause(err) != testCase.expectedErr { t.Errorf("Test case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err) } } else { - if err = fsRemoveDir(pathJoin(testCase.srcFSPath, testCase.srcVol, testCase.srcPath)); err != testCase.expectedErr { + if err = fsRemoveDir(pathJoin(testCase.srcFSPath, testCase.srcVol, testCase.srcPath)); errorCause(err) != testCase.expectedErr { t.Error(err) } } @@ -388,11 +388,11 @@ func TestFSRemoves(t *testing.T) { t.Fatal(err) } - if err = fsRemoveAll(""); err != errInvalidArgument { + if err = fsRemoveAll(""); errorCause(err) != errInvalidArgument { t.Fatal(err) } - if err = fsRemoveAll("my-obj-del-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); err != errFileNameTooLong { + if err = fsRemoveAll("my-obj-del-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); errorCause(err) != errFileNameTooLong { t.Fatal(err) } } diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index a9f55a5ea..bc4d398fd 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -633,7 +633,7 @@ func (fs fsObjects) listObjectParts(bucket, object, uploadID string, partNumberM partNamePath := pathJoin(fs.fsPath, minioMetaMultipartBucket, uploadIDPath, part.Name) fi, err = fsStatFile(partNamePath) if err != nil { - return ListPartsInfo{}, toObjectErr(traceError(err), minioMetaMultipartBucket, partNamePath) + return ListPartsInfo{}, toObjectErr(err, minioMetaMultipartBucket, partNamePath) } result.Parts = append(result.Parts, partInfo{ PartNumber: part.Number, @@ -883,7 +883,7 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload multipartObjectDir := pathJoin(fs.fsPath, minioMetaMultipartBucket, bucket, object) multipartUploadIDDir := pathJoin(multipartObjectDir, uploadID) if err = fsRemoveUploadIDPath(multipartObjectDir, multipartUploadIDDir); err != nil { - return ObjectInfo{}, toObjectErr(traceError(err), bucket, object) + return ObjectInfo{}, toObjectErr(err, bucket, object) } // Remove entry from `uploads.json`. @@ -893,7 +893,7 @@ func (fs fsObjects) CompleteMultipartUpload(bucket string, object string, upload fi, err := fsStatFile(fsNSObjPath) if err != nil { - return ObjectInfo{}, toObjectErr(traceError(err), bucket, object) + return ObjectInfo{}, toObjectErr(err, bucket, object) } // Return object info. @@ -961,7 +961,7 @@ func (fs fsObjects) AbortMultipartUpload(bucket, object, uploadID string) error multipartObjectDir := pathJoin(fs.fsPath, minioMetaMultipartBucket, bucket, object) multipartUploadIDDir := pathJoin(multipartObjectDir, uploadID) if err = fsRemoveUploadIDPath(multipartObjectDir, multipartUploadIDDir); err != nil { - return toObjectErr(traceError(err), bucket, object) + return toObjectErr(err, bucket, object) } // Remove entry from `uploads.json`. diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index 2a455089f..16f3263a3 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -245,7 +245,7 @@ func (fs fsObjects) statBucketDir(bucket string) (os.FileInfo, error) { } st, err := fsStatDir(bucketDir) if err != nil { - return nil, traceError(err) + return nil, err } return st, nil } @@ -259,7 +259,7 @@ func (fs fsObjects) MakeBucket(bucket string) error { } if err = fsMkdir(bucketDir); err != nil { - return toObjectErr(traceError(err), bucket) + return toObjectErr(err, bucket) } return nil @@ -283,7 +283,7 @@ func (fs fsObjects) GetBucketInfo(bucket string) (BucketInfo, error) { // ListBuckets - list all s3 compatible buckets (directories) at fsPath. func (fs fsObjects) ListBuckets() ([]BucketInfo, error) { if err := checkPathLength(fs.fsPath); err != nil { - return nil, err + return nil, traceError(err) } var bucketInfos []BucketInfo entries, err := readDir(preparePath(fs.fsPath)) @@ -301,9 +301,9 @@ func (fs fsObjects) ListBuckets() ([]BucketInfo, error) { fi, err = fsStatDir(pathJoin(fs.fsPath, entry)) if err != nil { // If the directory does not exist, skip the entry. - if err == errVolumeNotFound { + if errorCause(err) == errVolumeNotFound { continue - } else if err == errVolumeAccessDenied { + } else if errorCause(err) == errVolumeAccessDenied { // Skip the entry if its a file. continue } @@ -376,7 +376,7 @@ func (fs fsObjects) CopyObject(srcBucket, srcObject, dstBucket, dstObject string // Stat the file to get file size. fi, err := fsStatFile(pathJoin(fs.fsPath, srcBucket, srcObject)) if err != nil { - return ObjectInfo{}, toObjectErr(traceError(err), srcBucket, srcObject) + return ObjectInfo{}, toObjectErr(err, srcBucket, srcObject) } // Check if this request is only metadata update. @@ -386,7 +386,7 @@ func (fs fsObjects) CopyObject(srcBucket, srcObject, dstBucket, dstObject string var wlk *lock.LockedFile wlk, err = fs.rwPool.Write(fsMetaPath) if err != nil { - return ObjectInfo{}, toObjectErr(err, srcBucket, srcObject) + return ObjectInfo{}, toObjectErr(traceError(err), srcBucket, srcObject) } // This close will allow for locks to be synchronized on `fs.json`. defer wlk.Close() @@ -467,7 +467,7 @@ func (fs fsObjects) GetObject(bucket, object string, offset int64, length int64, fsObjPath := pathJoin(fs.fsPath, bucket, object) reader, size, err := fsOpenFile(fsObjPath, offset) if err != nil { - return toObjectErr(traceError(err), bucket, object) + return toObjectErr(err, bucket, object) } defer reader.Close() @@ -523,7 +523,7 @@ func (fs fsObjects) getObjectInfo(bucket, object string) (ObjectInfo, error) { // Stat the file to get file size. fi, err := fsStatFile(pathJoin(fs.fsPath, bucket, object)) if err != nil { - return ObjectInfo{}, toObjectErr(traceError(err), bucket, object) + return ObjectInfo{}, toObjectErr(err, bucket, object) } return fsMeta.ToObjectInfo(bucket, object, fi), nil @@ -574,7 +574,7 @@ func (fs fsObjects) PutObject(bucket string, object string, size int64, data io. fsMetaPath := pathJoin(fs.fsPath, minioMetaBucket, bucketMetaPrefix, bucket, object, fsMetaJSONFile) wlk, err = fs.rwPool.Create(fsMetaPath) if err != nil { - return ObjectInfo{}, toObjectErr(err, bucket, object) + return ObjectInfo{}, toObjectErr(traceError(err), bucket, object) } // This close will allow for locks to be synchronized on `fs.json`. defer wlk.Close() @@ -672,7 +672,7 @@ func (fs fsObjects) PutObject(bucket string, object string, size int64, data io. // Stat the file to fetch timestamp, size. fi, err := fsStatFile(pathJoin(fs.fsPath, bucket, object)) if err != nil { - return ObjectInfo{}, toObjectErr(traceError(err), bucket, object) + return ObjectInfo{}, toObjectErr(err, bucket, object) } // Success. @@ -699,20 +699,20 @@ func (fs fsObjects) DeleteObject(bucket, object string) error { defer rwlk.Close() } if lerr != nil && lerr != errFileNotFound { - return toObjectErr(lerr, bucket, object) + return toObjectErr(traceError(lerr), bucket, object) } } // Delete the object. if err := fsDeleteFile(pathJoin(fs.fsPath, bucket), pathJoin(fs.fsPath, bucket, object)); err != nil { - return toObjectErr(traceError(err), bucket, object) + return toObjectErr(err, bucket, object) } if bucket != minioMetaBucket { // Delete the metadata object. err := fsDeleteFile(minioMetaBucketDir, fsMetaPath) - if err != nil && err != errFileNotFound { - return toObjectErr(traceError(err), bucket, object) + if err != nil && errorCause(err) != errFileNotFound { + return toObjectErr(err, bucket, object) } } return nil @@ -790,7 +790,7 @@ func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKey var fi os.FileInfo fi, err = fsStatFile(pathJoin(fs.fsPath, bucket, entry)) if err != nil { - return ObjectInfo{}, toObjectErr(traceError(err), bucket, entry) + return ObjectInfo{}, toObjectErr(err, bucket, entry) } fsMeta := fsMetaV1{} return fsMeta.ToObjectInfo(bucket, entry, fi), nil From 85f2b74cfda5eb4ebc660aff273d1f7e41ee86bd Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 26 Jan 2017 16:51:51 -0800 Subject: [PATCH 10/75] jwt: Cache the bcrypt password hash. (#3526) Creds don't require secretKeyHash to be calculated everytime, cache it instead and re-use. This is an optimization for bcrypt. Relevant results from the benchmark done locally, negative value means improvement in this scenario. ``` benchmark old ns/op new ns/op delta BenchmarkAuthenticateNode-4 160590992 80125647 -50.11% BenchmarkAuthenticateWeb-4 160556692 80432144 -49.90% benchmark old allocs new allocs delta BenchmarkAuthenticateNode-4 87 75 -13.79% BenchmarkAuthenticateWeb-4 87 75 -13.79% benchmark old bytes new bytes delta BenchmarkAuthenticateNode-4 15222 9785 -35.72% BenchmarkAuthenticateWeb-4 15222 9785 -35.72% ``` --- appveyor.yml | 4 ++-- cmd/admin-handlers.go | 4 ++-- cmd/admin-handlers_test.go | 6 ++---- cmd/auth-handler_test.go | 7 ++++++- cmd/browser-peer-rpc.go | 7 ++++++- cmd/config-v13.go | 12 +++++++++++- cmd/credential.go | 28 ++++++++++++++++++++++++---- cmd/globals.go | 7 ++----- cmd/jwt.go | 3 +-- cmd/jwt_test.go | 34 ++++++++++++++++++++++++++++++++-- cmd/main.go | 20 +++++++------------- cmd/web-handlers.go | 17 ++++++----------- cmd/web-handlers_test.go | 8 -------- 13 files changed, 101 insertions(+), 56 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7488c103a..2e1dfd420 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,8 +35,8 @@ test_script: # Unit tests - ps: Add-AppveyorTest "Unit Tests" -Outcome Running - mkdir build\coverage - - go test -timeout 15m -v -race github.com/minio/minio/cmd... - - go test -v -race github.com/minio/minio/pkg... + - go test -timeout 15m -race github.com/minio/minio/cmd... + - go test -race github.com/minio/minio/pkg... - go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd - ps: Update-AppveyorTest "Unit Tests" -Outcome Passed diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index b83f49652..5fdfbd47e 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -131,8 +131,8 @@ func (adminAPI adminAPIHandlers) ServiceCredentialsHandler(w http.ResponseWriter } // Avoid setting new credentials when they are already passed - // by the environnement - if globalEnvAccessKey != "" || globalEnvSecretKey != "" { + // by the environment. + if globalIsEnvCreds { writeErrorResponse(w, ErrMethodNotAllowed, r.URL) return } diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index 22c406d1e..dea04ef70 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -294,11 +294,9 @@ func TestServiceSetCreds(t *testing.T) { for i, testCase := range testCases { // Set or unset environement keys if !testCase.EnvKeysSet { - globalEnvAccessKey = "" - globalEnvSecretKey = "" + globalIsEnvCreds = false } else { - globalEnvAccessKey = testCase.Username - globalEnvSecretKey = testCase.Password + globalIsEnvCreds = true } // Construct setCreds request body diff --git a/cmd/auth-handler_test.go b/cmd/auth-handler_test.go index de9d8e124..fc48afc6c 100644 --- a/cmd/auth-handler_test.go +++ b/cmd/auth-handler_test.go @@ -315,7 +315,12 @@ func TestIsReqAuthenticated(t *testing.T) { } defer removeAll(path) - serverConfig.SetCredential(credential{"myuser", "mypassword"}) + creds, err := getCredential("myuser", "mypassword") + if err != nil { + t.Fatal(err) + } + + serverConfig.SetCredential(creds) // List of test cases for validating http request authentication. testCases := []struct { diff --git a/cmd/browser-peer-rpc.go b/cmd/browser-peer-rpc.go index 79f9e7b53..335e0b770 100644 --- a/cmd/browser-peer-rpc.go +++ b/cmd/browser-peer-rpc.go @@ -63,8 +63,13 @@ func (br *browserPeerAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *AuthR return err } + creds, err := getCredential(args.Creds.AccessKey, args.Creds.SecretKey) + if err != nil { + return err + } + // Update credentials in memory - serverConfig.SetCredential(args.Creds) + serverConfig.SetCredential(creds) // Save credentials to config file if err := serverConfig.Save(); err != nil { diff --git a/cmd/config-v13.go b/cmd/config-v13.go index 5ba8b78c6..7b014fb6c 100644 --- a/cmd/config-v13.go +++ b/cmd/config-v13.go @@ -90,10 +90,12 @@ func initConfig() (bool, error) { // Save config into file. return true, serverConfig.Save() } + configFile, err := getConfigFile() if err != nil { return false, err } + if _, err = os.Stat(configFile); err != nil { return false, err } @@ -103,7 +105,13 @@ func initConfig() (bool, error) { if err != nil { return false, err } - if err := qc.Load(configFile); err != nil { + + if err = qc.Load(configFile); err != nil { + return false, err + } + + srvCfg.Credential, err = getCredential(srvCfg.Credential.AccessKey, srvCfg.Credential.SecretKey) + if err != nil { return false, err } @@ -112,6 +120,7 @@ func initConfig() (bool, error) { // Save the loaded config globally. serverConfig = srvCfg serverConfigMu.Unlock() + // Set the version properly after the unmarshalled json is loaded. serverConfig.Version = globalMinioConfigVersion @@ -337,6 +346,7 @@ func (s *serverConfigV13) SetCredential(creds credential) { serverConfigMu.Lock() defer serverConfigMu.Unlock() + // Set updated credential. s.Credential = creds } diff --git a/cmd/credential.go b/cmd/credential.go index 4d84c9301..aad1749b1 100644 --- a/cmd/credential.go +++ b/cmd/credential.go @@ -19,6 +19,8 @@ package cmd import ( "crypto/rand" "encoding/base64" + + "golang.org/x/crypto/bcrypt" ) const ( @@ -65,14 +67,31 @@ func isSecretKeyValid(secretKey string) bool { // credential container for access and secret keys. type credential struct { - AccessKey string `json:"accessKey"` - SecretKey string `json:"secretKey"` + AccessKey string `json:"accessKey,omitempty"` + SecretKey string `json:"secretKey,omitempty"` + SecretKeyHash []byte `json:"secretKeyHash,omitempty"` } +// Generate a bcrypt hashed key for input secret key. +func mustGetHashedSecretKey(secretKey string) []byte { + hashedSecretKey, err := bcrypt.GenerateFromPassword([]byte(secretKey), bcrypt.DefaultCost) + if err != nil { + panic(err) + } + return hashedSecretKey +} + +// Initialize a new credential object. func newCredential() credential { - return credential{mustGetAccessKey(), mustGetSecretKey()} + secretKey := mustGetSecretKey() + accessKey := mustGetAccessKey() + + secretHash := mustGetHashedSecretKey(secretKey) + return credential{accessKey, secretKey, secretHash} } +// Converts accessKey and secretKeys into credential object which +// contains bcrypt secret key hash for future validation. func getCredential(accessKey, secretKey string) (credential, error) { if !isAccessKeyValid(accessKey) { return credential{}, errInvalidAccessKeyLength @@ -82,5 +101,6 @@ func getCredential(accessKey, secretKey string) (credential, error) { return credential{}, errInvalidSecretKeyLength } - return credential{accessKey, secretKey}, nil + secretHash := mustGetHashedSecretKey(secretKey) + return credential{accessKey, secretKey, secretHash}, nil } diff --git a/cmd/globals.go b/cmd/globals.go index eaa0508e5..4eed8972b 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -110,11 +110,8 @@ var ( // Minio server user agent string. globalServerUserAgent = "Minio/" + ReleaseTag + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")" - // Global server's access key - globalEnvAccessKey = "" - - // Global server's secret key - globalEnvSecretKey = "" + // Set to true if credentials were passed from env, default is false. + globalIsEnvCreds = false // url.URL endpoints of disks that belong to the object storage. globalEndpoints = []*url.URL{} diff --git a/cmd/jwt.go b/cmd/jwt.go index 549617cab..c3d80a08f 100644 --- a/cmd/jwt.go +++ b/cmd/jwt.go @@ -65,8 +65,7 @@ func authenticateJWT(accessKey, secretKey string, expiry time.Duration) (string, // Validate secret key. // Using bcrypt to avoid timing attacks. - hashedSecretKey, _ := bcrypt.GenerateFromPassword([]byte(serverCred.SecretKey), bcrypt.DefaultCost) - if bcrypt.CompareHashAndPassword(hashedSecretKey, []byte(secretKey)) != nil { + if bcrypt.CompareHashAndPassword(serverCred.SecretKeyHash, []byte(secretKey)) != nil { return "", errAuthentication } diff --git a/cmd/jwt_test.go b/cmd/jwt_test.go index 32cdfa8fe..c8b531269 100644 --- a/cmd/jwt_test.go +++ b/cmd/jwt_test.go @@ -75,10 +75,40 @@ func testAuthenticate(authType string, t *testing.T) { } } -func TestNodeAuthenticate(t *testing.T) { +func TestAuthenticateNode(t *testing.T) { testAuthenticate("node", t) } -func TestWebAuthenticate(t *testing.T) { +func TestAuthenticateWeb(t *testing.T) { testAuthenticate("web", t) } + +func BenchmarkAuthenticateNode(b *testing.B) { + testPath, err := newTestConfig(globalMinioDefaultRegion) + if err != nil { + b.Fatalf("unable initialize config file, %s", err) + } + defer removeAll(testPath) + + creds := serverConfig.GetCredential() + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + authenticateNode(creds.AccessKey, creds.SecretKey) + } +} + +func BenchmarkAuthenticateWeb(b *testing.B) { + testPath, err := newTestConfig(globalMinioDefaultRegion) + if err != nil { + b.Fatalf("unable initialize config file, %s", err) + } + defer removeAll(testPath) + + creds := serverConfig.GetCredential() + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + authenticateWeb(creds.AccessKey, creds.SecretKey) + } +} diff --git a/cmd/main.go b/cmd/main.go index 0038042ea..57c42772a 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -190,20 +190,14 @@ func minioInit(ctx *cli.Context) { enableLoggers() // Fetch access keys from environment variables and update the config. - globalEnvAccessKey = os.Getenv("MINIO_ACCESS_KEY") - globalEnvSecretKey = os.Getenv("MINIO_SECRET_KEY") - if globalEnvAccessKey != "" && globalEnvSecretKey != "" { + accessKey := os.Getenv("MINIO_ACCESS_KEY") + secretKey := os.Getenv("MINIO_SECRET_KEY") + if accessKey != "" && secretKey != "" { + creds, err := getCredential(accessKey, secretKey) + fatalIf(err, "Credentials are invalid, please set proper credentials `minio server --help`") + // Set new credentials. - serverConfig.SetCredential(credential{ - AccessKey: globalEnvAccessKey, - SecretKey: globalEnvSecretKey, - }) - } - if !isAccessKeyValid(serverConfig.GetCredential().AccessKey) { - fatalIf(errInvalidArgument, "Invalid access key. Accept only a string starting with a alphabetic and containing from 5 to 20 characters.") - } - if !isSecretKeyValid(serverConfig.GetCredential().SecretKey) { - fatalIf(errInvalidArgument, "Invalid secret key. Accept only a string containing from 8 to 40 characters.") + serverConfig.SetCredential(creds) } // Init the error tracing module. diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 8346ef944..adf9f6db7 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -363,16 +363,18 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se } // As we already validated the authentication, we save given access/secret keys. - cred, err := getCredential(args.AccessKey, args.SecretKey) + creds, err := getCredential(args.AccessKey, args.SecretKey) if err != nil { return toJSONError(err) } // Notify all other Minio peers to update credentials - errsMap := updateCredsOnPeers(cred) + errsMap := updateCredsOnPeers(creds) // Update local credentials - serverConfig.SetCredential(cred) + serverConfig.SetCredential(creds) + + // Persist updated credentials. if err = serverConfig.Save(); err != nil { errsMap[globalMinioAddr] = err } @@ -506,14 +508,7 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) { objectLock.RLock() defer objectLock.RUnlock() - objInfo, err := objectAPI.GetObjectInfo(bucket, object) - if err != nil { - writeWebErrorResponse(w, err) - return - } - offset := int64(0) - err = objectAPI.GetObject(bucket, object, offset, objInfo.Size, w) - if err != nil { + if err := objectAPI.GetObject(bucket, object, 0, -1, w); err != nil { /// No need to print error, response writer already written to. return } diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index 238713078..fc72ab9ff 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -1533,10 +1533,6 @@ func TestWebObjectLayerFaultyDisks(t *testing.T) { if rec.Code != http.StatusOK { t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) } - resp := string(rec.Body.Bytes()) - if !strings.Contains(resp, "We encountered an internal error, please try again.") { - t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp) - } // Test authorization of Web.Upload content := []byte("temporary file's content") @@ -1553,8 +1549,4 @@ func TestWebObjectLayerFaultyDisks(t *testing.T) { if rec.Code != http.StatusOK { t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) } - resp = string(rec.Body.Bytes()) - if !strings.Contains(resp, "We encountered an internal error, please try again.") { - t.Fatalf("Unexpected error message, expected: `Invalid token`, found: `%s`", resp) - } } From 02194ee3c60fa341b658c05f2ef5ec47d3a15ff7 Mon Sep 17 00:00:00 2001 From: Alex Ellis Date: Fri, 27 Jan 2017 17:50:08 +0000 Subject: [PATCH 11/75] Fix issue with webhook events not closing Response body, leaving connections open with remote server (#3645) --- cmd/notify-webhook.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/notify-webhook.go b/cmd/notify-webhook.go index 95af0fcb4..875167f79 100644 --- a/cmd/notify-webhook.go +++ b/cmd/notify-webhook.go @@ -119,6 +119,9 @@ func (n httpConn) Fire(entry *logrus.Entry) error { return err } + // Make sure to close the response body so the connection can be re-used. + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted && resp.StatusCode != http.StatusContinue { From e1bc99e4fee12aa160a35409d66246c40d503f75 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Fri, 27 Jan 2017 19:51:02 +0100 Subject: [PATCH 12/75] xl: Fix GET of an empty multiparted object (#3646) GetObject returns unsatisfied range error when we try to download an object uploaded using multipart mechanism. --- cmd/xl-v1-object.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index 2e4c632ca..b3ea9b2ff 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -198,8 +198,14 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i return traceError(InvalidRange{startOffset, length, xlMeta.Stat.Size}) } + // Calculate endOffset according to length + endOffset := startOffset + if length > 0 { + endOffset += length - 1 + } + // Get last part index to read given length. - lastPartIndex, _, err := xlMeta.ObjectToPartOffset(startOffset + length - 1) + lastPartIndex, _, err := xlMeta.ObjectToPartOffset(endOffset) if err != nil { return traceError(InvalidRange{startOffset, length, xlMeta.Stat.Size}) } From ccd949d8ca068ddc406f58479132f2101c30493b Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 27 Jan 2017 12:31:02 -0800 Subject: [PATCH 13/75] Add -v for race tests to avoid travis and appveyor timeouts. (#3647) This is added so that CI's don't wrong fully timeout on little longer running tests. --- .travis.yml | 2 +- appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdf9bd708..cbe34000e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ env: script: - make -- make test GOFLAGS="-race" +- make test GOFLAGS="-race -v" - make coverage after_success: diff --git a/appveyor.yml b/appveyor.yml index 2e1dfd420..7488c103a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,8 +35,8 @@ test_script: # Unit tests - ps: Add-AppveyorTest "Unit Tests" -Outcome Running - mkdir build\coverage - - go test -timeout 15m -race github.com/minio/minio/cmd... - - go test -race github.com/minio/minio/pkg... + - go test -timeout 15m -v -race github.com/minio/minio/cmd... + - go test -v -race github.com/minio/minio/pkg... - go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd - ps: Update-AppveyorTest "Unit Tests" -Outcome Passed From 73f4f2911090575ae7a63265afdeaac58df6f98d Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 28 Jan 2017 19:45:30 -0800 Subject: [PATCH 14/75] docs: Restructure docs, move the files to their relevant location. (#3648) Also combines windows TLS docs with single doc with Linux. --- .../{management-api.md => README.md} | 0 docs/configure-minio-with-gnutls-windows.md | 68 ---------- docs/configure-minio-with-tls.md | 49 ------- docs/service/linux/README.md | 44 +++++++ .../windows/README.md} | 1 - docs/tls/README.md | 122 ++++++++++++++++++ 6 files changed, 166 insertions(+), 118 deletions(-) rename docs/admin-api/{management-api.md => README.md} (100%) delete mode 100644 docs/configure-minio-with-gnutls-windows.md delete mode 100644 docs/configure-minio-with-tls.md create mode 100644 docs/service/linux/README.md rename docs/{running-minio-as-a-service-on-windows.md => service/windows/README.md} (99%) create mode 100644 docs/tls/README.md diff --git a/docs/admin-api/management-api.md b/docs/admin-api/README.md similarity index 100% rename from docs/admin-api/management-api.md rename to docs/admin-api/README.md diff --git a/docs/configure-minio-with-gnutls-windows.md b/docs/configure-minio-with-gnutls-windows.md deleted file mode 100644 index b397e30d8..000000000 --- a/docs/configure-minio-with-gnutls-windows.md +++ /dev/null @@ -1,68 +0,0 @@ - -# Generate self signed certificate with GnuTLS under Windows - - -## 1. Install GnuTLS - -Download and decompress the Windows version of GnuTLS from [here](http://www.gnutls.org/download.html) - -Add the directory `gnutls-3.4.9-w64/bin` to your PATH environment and restart your console - -## 2. Generate private.key - -Run the following command to create `private.key` -``` -certtool.exe --generate-privkey --outfile private.key -``` - -## 3. Generate public.crt - -The easiest way is to generate certificate is to specify its information under a file. You can find an example below. We'll call that file `cert.cnf`. - -``` -# X.509 Certificate options -# -# DN options - -# The organization of the subject. -organization = "Example Inc." - -# The organizational unit of the subject. -#unit = "sleeping dept." - -# The state of the certificate owner. -state = "Example" - -# The country of the subject. Two letter code. -country = "EX" - -# The common name of the certificate owner. -cn = "Sally Certowner" - -# In how many days, counting from today, this certificate will expire. -expiration_days = 365 - -# X.509 v3 extensions - -# DNS name(s) of the server -dns_name = "localhost" - -# (Optional) Server IP address -ip_address = "127.0.0.1" - -# Whether this certificate will be used for a TLS server -tls_www_server - -# Whether this certificate will be used to encrypt data (needed -# in TLS RSA ciphersuites). Note that it is preferred to use different -# keys for encryption and signing. -encryption_key -``` - -Now, it is time to generate the public certificate using this command: - -```sh -certtool.exe --generate-self-signed --load-privkey private.key --template cert.cnf --outfile public.crt -``` - -That's it. diff --git a/docs/configure-minio-with-tls.md b/docs/configure-minio-with-tls.md deleted file mode 100644 index 840f5628c..000000000 --- a/docs/configure-minio-with-tls.md +++ /dev/null @@ -1,49 +0,0 @@ -# How to secure access to your Minio server with TLS [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) - -In this document, we will show how to configure your Minio servers with TLS certificates. Steps for Windows could be found [here](https://github.com/minio/minio/blob/master/docs/configure-minio-with-gnutls-windows.md). - -## 1. Prerequisites - -* Download Minio server from [here](https://docs.minio.io/docs/minio) - -## 2. Generate TLS certificate - -Minio supports only key/certificate in PEM format. - -### With Letsencrypt - -Please explore [here](https://docs.minio.io/docs/generate-let-s-encypt-certificate-using-concert-for-minio) - -### With generate_cert.go (self-signed certificate) - -You need to download [generate_cert.go](https://golang.org/src/crypto/tls/generate_cert.go?m=text) which is a simple go tool for generating self-signed certificates but works for the most of cases. - -`generate_cert.go` already provides SAN certificates with DNS and IP entries: - -```sh - go run generate_cert.go -ca --host "10.10.0.3" -``` - -### With OpenSSL: - -Generate the private key: -```sh -openssl genrsa -out private.key 1024 -``` - -Generate the self-signed certificate: -```sh -openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=country/ST=state/L=location/O=organization/CN=domain" -``` - -## 3. Configure Minio with the generated certificate - -To make Minio aware about your generated key and certificate, you will need to put them under `certs` directory in your Minio config path (usually ~/.minio) using the names of `private.key` and `public.crt` for key and certificate files respectively. - -## 4. Install third parties CAs - -Minio can be configured to connect to other servers, whether Minio nodes or servers like NATs, Redis. If these servers use certificates that are not registered in one of the known certificates authorities, you can make Minio server trust these CAs by dropping these certificates under `~/.minio/certs/CAs/` in your Minio config path. - -# Explore Further -* [Minio Quickstart Guide](https://docs.minio.io/docs/minio-quickstart-guide) -* [Minio Client Complete Guide](https://docs.minio.io/docs/minio-client-complete-guide) diff --git a/docs/service/linux/README.md b/docs/service/linux/README.md new file mode 100644 index 000000000..84780b329 --- /dev/null +++ b/docs/service/linux/README.md @@ -0,0 +1,44 @@ +# Running Minio as a service on Linux + +## Install Minio service + +Systemctl is a controller for systemd system and service manager. This document assumes operating system to be Ubuntu 16.04 (LTS) with `systemctl`. + +Create a default minio startup config file at `/etc/default/minio`. `MINIO_VOLUMES` should be updated with the correct path. +``` +cat <> /etc/default/minio +# Local export path. +MINIO_VOLUMES="/mnt/export" +# Use if you want to run Minio on a custom port. +# MINIO_OPTS="--address :9001" + +EOT +``` + +Optionally you can also override your Minio access credentials as shown below. +``` +cat <> /etc/default/minio +# Access key of the server. +MINIO_ACCESS_KEY=YOUR-ACCESSKEY +# Secret key of the server. +MINIO_SECRET_KEY=YOUR-SECRETKEY + +EOT +``` + +Download `minio.service` into `/etc/systemd/system/` +``` +( cd /etc/systemd/system/; curl -O https://raw.githubusercontent.com/minio/minio-systemd/master/minio.service ) +``` + +## Enable Minio service + +Once we have successfully copied the `minio.service` we will enable it to start on boot. +``` +systemctl enable minio.service +``` + +## Disable Minio service +``` +systemctl disable minio.service +``` diff --git a/docs/running-minio-as-a-service-on-windows.md b/docs/service/windows/README.md similarity index 99% rename from docs/running-minio-as-a-service-on-windows.md rename to docs/service/windows/README.md index f459d6afe..3c10628bf 100644 --- a/docs/running-minio-as-a-service-on-windows.md +++ b/docs/service/windows/README.md @@ -23,7 +23,6 @@ It is a good (and secure) practice to create a new user, assign rights to the da ![Configure user](https://raw.githubusercontent.com/minio/minio/master/docs/screenshots/windows-configure-user.png) ## Delete Minio service - ``` c:\nssm.exe remove Minio ``` diff --git a/docs/tls/README.md b/docs/tls/README.md new file mode 100644 index 000000000..c879798d7 --- /dev/null +++ b/docs/tls/README.md @@ -0,0 +1,122 @@ +# How to secure access to Minio server with TLS [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) + +In this document, we will configure Minio servers with TLS certificates. Steps for Windows could be found [here](https://github.com/minio/minio/blob/master/docs/configure-minio-with-gnutls-windows.md). + +## 1. Prerequisites + +* Download Minio server from [here](https://docs.minio.io/docs/minio) + +## 2. Generate TLS certificate + +### Linux + +Minio supports only key/certificate in PEM format on Linux. + +#### With Let's Encrypt + +Please explore [here](https://docs.minio.io/docs/generate-let-s-encypt-certificate-using-concert-for-minio) + +#### With generate_cert.go (self-signed certificate) + +You need to download [generate_cert.go](https://golang.org/src/crypto/tls/generate_cert.go?m=text) which is a simple go tool for generating self-signed certificates but works for the most of cases. + +`generate_cert.go` already provides SAN certificates with DNS and IP entries: + +```sh + go run generate_cert.go -ca --host "10.10.0.3" +``` + +#### With OpenSSL: + +Generate the private key: +```sh +openssl genrsa -out private.key 1024 +``` + +Generate the self-signed certificate: +```sh +openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=country/ST=state/L=location/O=organization/CN=domain" +``` + +### Windows + +Minio only supports key/certificate in PEM format on Windows. Currently we do not yet support PFX certificates. + +#### Install GnuTLS + +Download and decompress the Windows version of GnuTLS from [here](http://www.gnutls.org/download.html) + +Make sure to add extracted GnuTLS binary path to your system path. +``` +setx path "%path%;C:\Users\MyUser\Downloads\gnutls-3.4.9-w64\bin" +``` + +You may need to restart your powershell console for this to take affect. + +#### Generate private.key + +Run the following command to create `private.key` +``` +certtool.exe --generate-privkey --outfile private.key +``` + +#### Generate public.crt + +Create a file `cert.cnf` with all the necessary information to generate a certificate. + +``` +# X.509 Certificate options +# +# DN options + +# The organization of the subject. +organization = "Example Inc." + +# The organizational unit of the subject. +#unit = "sleeping dept." + +# The state of the certificate owner. +state = "Example" + +# The country of the subject. Two letter code. +country = "EX" + +# The common name of the certificate owner. +cn = "Sally Certowner" + +# In how many days, counting from today, this certificate will expire. +expiration_days = 365 + +# X.509 v3 extensions + +# DNS name(s) of the server +dns_name = "localhost" + +# (Optional) Server IP address +ip_address = "127.0.0.1" + +# Whether this certificate will be used for a TLS server +tls_www_server + +# Whether this certificate will be used to encrypt data (needed +# in TLS RSA ciphersuites). Note that it is preferred to use different +# keys for encryption and signing. +encryption_key +``` + +Generate public certificate +``` +certtool.exe --generate-self-signed --load-privkey private.key --template cert.cnf --outfile public.crt +``` + +## 3. Configure Minio with the generated certificate + +Copy the generated key and certificate under `certs` in your Minio config path (by default in your HOME directory `~/.minio` on Linux or `C:\Users\\.minio` on Windows) using the names `private.key` and `public.crt` for key and certificate files respectively. + +## 4. Install third-party CAs + +Minio can be configured to connect to other servers, whether Minio nodes or servers like NATs, Redis. If these servers use certificates that are not registered in one of the known certificates authorities, you can make Minio server trust these CAs by dropping these certificates under Minio config path (`~/.minio/certs/CAs/` on Linux or `C:\Users\\.minio\certs\CAs` on Windows). + +# Explore Further +* [Minio Quickstart Guide](https://docs.minio.io/docs/minio-quickstart-guide) +* [Minio Client Complete Guide](https://docs.minio.io/docs/minio-client-complete-guide) From 5af7bd6a0194a966f96df63f6fb7cd75811d89ff Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 28 Jan 2017 22:41:47 -0800 Subject: [PATCH 15/75] docs: Fix a typo in TLS doc description --- docs/tls/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tls/README.md b/docs/tls/README.md index c879798d7..826423137 100644 --- a/docs/tls/README.md +++ b/docs/tls/README.md @@ -1,6 +1,6 @@ # How to secure access to Minio server with TLS [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) -In this document, we will configure Minio servers with TLS certificates. Steps for Windows could be found [here](https://github.com/minio/minio/blob/master/docs/configure-minio-with-gnutls-windows.md). +In this document, we will configure Minio servers with TLS certificates for both Linux and Windows. ## 1. Prerequisites From cf558ff6d1d5ee4747941c09b90f3bc35c264e47 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 28 Jan 2017 22:45:36 -0800 Subject: [PATCH 16/75] docs: Fix TLS doc to be docs.minio.io compatible --- docs/tls/README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/tls/README.md b/docs/tls/README.md index 826423137..57f2ff8c1 100644 --- a/docs/tls/README.md +++ b/docs/tls/README.md @@ -23,19 +23,27 @@ You need to download [generate_cert.go](https://golang.org/src/crypto/tls/genera `generate_cert.go` already provides SAN certificates with DNS and IP entries: ```sh - go run generate_cert.go -ca --host "10.10.0.3" + +go run generate_cert.go -ca --host "10.10.0.3" + ``` #### With OpenSSL: Generate the private key: + ```sh + openssl genrsa -out private.key 1024 + ``` Generate the self-signed certificate: + ```sh + openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=country/ST=state/L=location/O=organization/CN=domain" + ``` ### Windows @@ -47,8 +55,11 @@ Minio only supports key/certificate in PEM format on Windows. Currently we do no Download and decompress the Windows version of GnuTLS from [here](http://www.gnutls.org/download.html) Make sure to add extracted GnuTLS binary path to your system path. + ``` + setx path "%path%;C:\Users\MyUser\Downloads\gnutls-3.4.9-w64\bin" + ``` You may need to restart your powershell console for this to take affect. @@ -56,8 +67,11 @@ You may need to restart your powershell console for this to take affect. #### Generate private.key Run the following command to create `private.key` + ``` + certtool.exe --generate-privkey --outfile private.key + ``` #### Generate public.crt @@ -105,8 +119,11 @@ encryption_key ``` Generate public certificate + ``` + certtool.exe --generate-self-signed --load-privkey private.key --template cert.cnf --outfile public.crt + ``` ## 3. Configure Minio with the generated certificate From 69b81af93e20bad8f3d8ec79c262b0b6558047c3 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Sun, 29 Jan 2017 16:21:30 +0100 Subject: [PATCH 17/75] Fix Minio quick start guide URL (#3655) --- docs/distributed/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/distributed/README.md b/docs/distributed/README.md index 04e4ab302..a76002f24 100644 --- a/docs/distributed/README.md +++ b/docs/distributed/README.md @@ -28,7 +28,7 @@ If you're aware of stand-alone Minio set up, the process remains largely the sam ## 1. Prerequisites -Install Minio - [Minio Quickstart Guide](https://docs.minio.io/docs/minio). +Install Minio - [Minio Quickstart Guide](https://docs.minio.io/docs/minio-quickstart-guide). ## 2. Run distributed Minio From b408d0e87dcaaabf28d9730954b6e0f307e18018 Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Mon, 30 Jan 2017 09:15:11 +0530 Subject: [PATCH 18/75] Add aws:Referer condition key support. (#3641) This change implements bucket policy enhancements required to restrict access based on HTTP referer. See https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-4 for more information. Fixes #3540 --- cmd/auth-handler.go | 3 +- cmd/bucket-handlers.go | 15 ++-- cmd/bucket-policy-handlers.go | 46 +++++++++--- cmd/bucket-policy-handlers_test.go | 28 ++++++++ cmd/bucket-policy-parser.go | 4 +- cmd/bucket-policy-parser_test.go | 111 ++++++++++++++++++++++++----- cmd/object-handlers.go | 13 ++-- docs/bucket/policy/README.md | 3 + 8 files changed, 181 insertions(+), 42 deletions(-) diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index a50219d59..a48989f12 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -125,7 +125,8 @@ func checkRequestAuthType(r *http.Request, bucket, policyAction, region string) if reqAuthType == authTypeAnonymous && policyAction != "" { // http://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html - return enforceBucketPolicy(bucket, policyAction, r.URL) + return enforceBucketPolicy(bucket, policyAction, r.URL.Path, + r.Referer(), r.URL.Query()) } // By default return ErrAccessDenied diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 95227f4af..db942d755 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -33,7 +33,7 @@ import ( // http://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html // Enforces bucket policies for a bucket for a given tatusaction. -func enforceBucketPolicy(bucket string, action string, reqURL *url.URL) (s3Error APIErrorCode) { +func enforceBucketPolicy(bucket, action, resource, referer string, queryParams url.Values) (s3Error APIErrorCode) { // Verify if bucket actually exists if err := checkBucketExist(bucket, newObjectLayerFn()); err != nil { err = errorCause(err) @@ -57,16 +57,21 @@ func enforceBucketPolicy(bucket string, action string, reqURL *url.URL) (s3Error } // Construct resource in 'arn:aws:s3:::examplebucket/object' format. - resource := bucketARNPrefix + strings.TrimSuffix(strings.TrimPrefix(reqURL.Path, "/"), "/") + arn := bucketARNPrefix + strings.TrimSuffix(strings.TrimPrefix(resource, "/"), "/") // Get conditions for policy verification. conditionKeyMap := make(map[string]set.StringSet) - for queryParam := range reqURL.Query() { - conditionKeyMap[queryParam] = set.CreateStringSet(reqURL.Query().Get(queryParam)) + for queryParam := range queryParams { + conditionKeyMap[queryParam] = set.CreateStringSet(queryParams.Get(queryParam)) + } + + // Add request referer to conditionKeyMap if present. + if referer != "" { + conditionKeyMap["referer"] = set.CreateStringSet(referer) } // Validate action, resource and conditions with current policy statements. - if !bucketPolicyEvalStatements(action, resource, conditionKeyMap, policy.Statements) { + if !bucketPolicyEvalStatements(action, arn, conditionKeyMap, policy.Statements) { return ErrAccessDenied } return ErrNone diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index 7a525dd95..c856e38e8 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -71,6 +71,10 @@ func actionMatch(pattern, action string) bool { return wildcard.MatchSimple(pattern, action) } +func refererMatch(pattern, referer string) bool { + return wildcard.MatchSimple(pattern, referer) +} + // Verify if given resource matches with policy statement. func bucketPolicyResourceMatch(resource string, statement policyStatement) bool { // the resource rule for object could contain "*" wild card. @@ -85,33 +89,55 @@ func bucketPolicyConditionMatch(conditions map[string]set.StringSet, statement p // Supports following conditions. // - StringEquals // - StringNotEquals + // - StringLike + // - StringNotLike // // Supported applicable condition keys for each conditions. // - s3:prefix // - s3:max-keys - var conditionMatches = true + // - s3:aws-Referer + for condition, conditionKeyVal := range statement.Conditions { if condition == "StringEquals" { if !conditionKeyVal["s3:prefix"].Equals(conditions["prefix"]) { - conditionMatches = false - break + return false } if !conditionKeyVal["s3:max-keys"].Equals(conditions["max-keys"]) { - conditionMatches = false - break + return false } } else if condition == "StringNotEquals" { if !conditionKeyVal["s3:prefix"].Equals(conditions["prefix"]) { - conditionMatches = false - break + return false } if !conditionKeyVal["s3:max-keys"].Equals(conditions["max-keys"]) { - conditionMatches = false - break + return false } + } else if condition == "StringLike" { + awsReferers := conditionKeyVal["aws:Referer"] + // wildcard match of referer in statement was not empty. + // StringLike has a match, i.e, condition evaluates to true. + for referer := range conditions["referer"] { + if !awsReferers.FuncMatch(refererMatch, referer).IsEmpty() { + return true + } + } + // No matching referer found, so the condition is false. + return false + } else if condition == "StringNotLike" { + awsReferers := conditionKeyVal["aws:Referer"] + // wildcard match of referer in statement was not empty. + // StringNotLike has a match, i.e, condition evaluates to false. + for referer := range conditions["referer"] { + if !awsReferers.FuncMatch(refererMatch, referer).IsEmpty() { + return false + } + } + // No matching referer found, so the condition is true. + return true } } - return conditionMatches + // No conditions were present in the statement, so trivially true (always). + return true } // PutBucketPolicyHandler - PUT Bucket policy diff --git a/cmd/bucket-policy-handlers_test.go b/cmd/bucket-policy-handlers_test.go index cfc690ef7..999dc5530 100644 --- a/cmd/bucket-policy-handlers_test.go +++ b/cmd/bucket-policy-handlers_test.go @@ -942,6 +942,34 @@ func TestBucketPolicyConditionMatch(t *testing.T) { expectedMatch: false, }, + // Test case - 9. + // StringLike condition matches. + { + statementCondition: getStatementWithCondition("StringLike", "aws:Referer", "http://www.example.com/"), + condition: getInnerMap("referer", "http://www.example.com/"), + expectedMatch: true, + }, + // Test case - 10. + // StringLike condition doesn't match. + { + statementCondition: getStatementWithCondition("StringLike", "aws:Referer", "http://www.example.com/"), + condition: getInnerMap("referer", "www.somethingelse.com"), + expectedMatch: false, + }, + // Test case - 11. + // StringNotLike condition evaluates to false. + { + statementCondition: getStatementWithCondition("StringNotLike", "aws:Referer", "http://www.example.com/"), + condition: getInnerMap("referer", "http://www.example.com/"), + expectedMatch: false, + }, + // Test case - 12. + // StringNotLike condition evaluates to true. + { + statementCondition: getStatementWithCondition("StringNotLike", "aws:Referer", "http://www.example.com/"), + condition: getInnerMap("referer", "http://somethingelse.com/"), + expectedMatch: true, + }, } for i, tc := range testCases { diff --git a/cmd/bucket-policy-parser.go b/cmd/bucket-policy-parser.go index 1264a610c..f9324846c 100644 --- a/cmd/bucket-policy-parser.go +++ b/cmd/bucket-policy-parser.go @@ -35,11 +35,11 @@ var supportedActionMap = set.CreateStringSet("*", "s3:*", "s3:GetObject", "s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads", "s3:ListMultipartUploadParts") // supported Conditions type. -var supportedConditionsType = set.CreateStringSet("StringEquals", "StringNotEquals") +var supportedConditionsType = set.CreateStringSet("StringEquals", "StringNotEquals", "StringLike", "StringNotLike") // Validate s3:prefix, s3:max-keys are present if not // supported keys for the conditions. -var supportedConditionsKey = set.CreateStringSet("s3:prefix", "s3:max-keys") +var supportedConditionsKey = set.CreateStringSet("s3:prefix", "s3:max-keys", "aws:Referer") // supportedEffectMap - supported effects. var supportedEffectMap = set.CreateStringSet("Allow", "Deny") diff --git a/cmd/bucket-policy-parser_test.go b/cmd/bucket-policy-parser_test.go index 522dc2c63..a9418db1f 100644 --- a/cmd/bucket-policy-parser_test.go +++ b/cmd/bucket-policy-parser_test.go @@ -22,6 +22,7 @@ import ( "fmt" "testing" + "github.com/minio/minio-go/pkg/policy" "github.com/minio/minio-go/pkg/set" ) @@ -342,6 +343,18 @@ func TestIsValidPrincipals(t *testing.T) { } } +// getEmptyConditionKeyMap - returns a function that generates a +// condition key map for a given key. +func getEmptyConditionKeyMap(conditionKey string) func() map[string]map[string]set.StringSet { + emptyConditonGenerator := func() map[string]map[string]set.StringSet { + emptyMap := make(map[string]set.StringSet) + conditions := make(map[string]map[string]set.StringSet) + conditions[conditionKey] = emptyMap + return conditions + } + return emptyConditonGenerator +} + // Tests validate policyStatement condition validator. func TestIsValidConditions(t *testing.T) { // returns empty conditions map. @@ -350,22 +363,17 @@ func TestIsValidConditions(t *testing.T) { } // returns map with the "StringEquals" set to empty map. - setEmptyStringEquals := func() map[string]map[string]set.StringSet { - emptyMap := make(map[string]set.StringSet) - conditions := make(map[string]map[string]set.StringSet) - conditions["StringEquals"] = emptyMap - return conditions - - } + setEmptyStringEquals := getEmptyConditionKeyMap("StringEquals") // returns map with the "StringNotEquals" set to empty map. - setEmptyStringNotEquals := func() map[string]map[string]set.StringSet { - emptyMap := make(map[string]set.StringSet) - conditions := make(map[string]map[string]set.StringSet) - conditions["StringNotEquals"] = emptyMap - return conditions + setEmptyStringNotEquals := getEmptyConditionKeyMap("StringNotEquals") + + // returns map with the "StringLike" set to empty map. + setEmptyStringLike := getEmptyConditionKeyMap("StringLike") + + // returns map with the "StringNotLike" set to empty map. + setEmptyStringNotLike := getEmptyConditionKeyMap("StringNotLike") - } // Generate conditions. generateConditions := func(key1, key2, value string) map[string]map[string]set.StringSet { innerMap := make(map[string]set.StringSet) @@ -377,11 +385,11 @@ func TestIsValidConditions(t *testing.T) { // generate ambigious conditions. generateAmbigiousConditions := func() map[string]map[string]set.StringSet { - innerMap := make(map[string]set.StringSet) - innerMap["s3:prefix"] = set.CreateStringSet("Asia/") + prefixMap := make(map[string]set.StringSet) + prefixMap["s3:prefix"] = set.CreateStringSet("Asia/") conditions := make(map[string]map[string]set.StringSet) - conditions["StringEquals"] = innerMap - conditions["StringNotEquals"] = innerMap + conditions["StringEquals"] = prefixMap + conditions["StringNotEquals"] = prefixMap return conditions } @@ -417,6 +425,8 @@ func TestIsValidConditions(t *testing.T) { setEmptyConditions(), setEmptyStringEquals(), setEmptyStringNotEquals(), + setEmptyStringLike(), + setEmptyStringNotLike(), generateConditions("StringEquals", "s3:prefix", "Asia/"), generateConditions("StringEquals", "s3:max-keys", "100"), generateConditions("StringNotEquals", "s3:prefix", "Asia/"), @@ -464,7 +474,11 @@ func TestIsValidConditions(t *testing.T) { {testConditions[9], nil, true}, // Test case - 11. {testConditions[10], nil, true}, - // Test case 10. + // Test case - 12. + {testConditions[11], nil, true}, + // Test case - 13. + {testConditions[11], nil, true}, + // Test case - 14. {testConditions[11], nil, true}, } for i, testCase := range testCases { @@ -709,3 +723,64 @@ func TestParseBucketPolicy(t *testing.T) { } } } + +func TestAWSRefererCondition(t *testing.T) { + resource := set.CreateStringSet([]string{ + fmt.Sprintf("%s%s", bucketARNPrefix, "minio-bucket"+"/"+"Asia"+"*"), + }...) + + conditionsKeyMap := make(policy.ConditionKeyMap) + conditionsKeyMap.Add("aws:Referer", + set.CreateStringSet("www.example.com", + "http://www.example.com")) + + requestConditionKeyMap := make(map[string]set.StringSet) + requestConditionKeyMap["referer"] = set.CreateStringSet("www.example.com") + + testCases := []struct { + effect string + conditionKey string + match bool + }{ + { + effect: "Allow", + conditionKey: "StringLike", + match: true, + }, + { + effect: "Allow", + conditionKey: "StringNotLike", + match: false, + }, + { + effect: "Deny", + conditionKey: "StringLike", + match: true, + }, + { + effect: "Deny", + conditionKey: "StringNotLike", + match: false, + }, + } + + for i, test := range testCases { + conditions := make(map[string]map[string]set.StringSet) + conditions[test.conditionKey] = conditionsKeyMap + + allowStatement := policyStatement{ + Sid: "Testing AWS referer condition", + Effect: test.effect, + Principal: map[string]interface{}{ + "AWS": "*", + }, + Resources: resource, + Conditions: conditions, + } + + if result := bucketPolicyConditionMatch(requestConditionKeyMap, allowStatement); result != test.match { + t.Errorf("Test %d - Expected conditons to evaluate to %v but got %v", + i+1, test.match, result) + } + } +} diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 73b10b32e..d7c2bec79 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -56,10 +56,9 @@ func setGetRespHeaders(w http.ResponseWriter, reqParams url.Values) { func errAllowableObjectNotFound(bucket string, r *http.Request) APIErrorCode { if getRequestAuthType(r) == authTypeAnonymous { //we care about the bucket as a whole, not a particular resource - url := *r.URL - url.Path = "/" + bucket - - if s3Error := enforceBucketPolicy(bucket, "s3:ListBucket", &url); s3Error != ErrNone { + resource := "/" + bucket + if s3Error := enforceBucketPolicy(bucket, "s3:ListBucket", resource, + r.Referer(), r.URL.Query()); s3Error != ErrNone { return ErrAccessDenied } } @@ -440,7 +439,8 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req return case authTypeAnonymous: // http://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html - if s3Error := enforceBucketPolicy(bucket, "s3:PutObject", r.URL); s3Error != ErrNone { + if s3Error := enforceBucketPolicy(bucket, "s3:PutObject", r.URL.Path, + r.Referer(), r.URL.Query()); s3Error != ErrNone { writeErrorResponse(w, s3Error, r.URL) return } @@ -600,7 +600,8 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http return case authTypeAnonymous: // http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html - if s3Error := enforceBucketPolicy(bucket, "s3:PutObject", r.URL); s3Error != ErrNone { + if s3Error := enforceBucketPolicy(bucket, "s3:PutObject", r.URL.Path, + r.Referer(), r.URL.Query()); s3Error != ErrNone { writeErrorResponse(w, s3Error, r.URL) return } diff --git a/docs/bucket/policy/README.md b/docs/bucket/policy/README.md index b642de294..a738ff2c9 100644 --- a/docs/bucket/policy/README.md +++ b/docs/bucket/policy/README.md @@ -22,11 +22,14 @@ This package implements parsing and validating bucket access policies based on A StringEquals StringNotEquals + StringLike + StringNotLike Supported applicable condition keys for each conditions. s3:prefix s3:max-keys + aws:Referer ### Nested policy support. From cc1575f9444334a0d145dd85a003604bde058b3c Mon Sep 17 00:00:00 2001 From: Bala FA Date: Mon, 30 Jan 2017 14:14:36 +0530 Subject: [PATCH 19/75] fix: do port availability check only on macOS. (#3654) On macOS, if a process already listens on 127.0.0.1:PORT, net.Listen() falls back to IPv6 address ie minio will start listening on IPv6 address whereas another (non-)minio process is listening on IPv4 of given port. To avoid this error sutiation we check for port availability only for macOS. Note: checkPortAvailability() tries to listen on given port and closes it. It is possible to have a disconnected client in this tiny window of time. --- cmd/checkport.go | 22 +++++----------------- cmd/server-main.go | 11 ++++++++--- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/cmd/checkport.go b/cmd/checkport.go index 489adfba3..648868520 100644 --- a/cmd/checkport.go +++ b/cmd/checkport.go @@ -22,25 +22,13 @@ import ( "syscall" ) -// Make sure that none of the other processes are listening on the -// specified port on any of the interfaces. -// -// On linux if a process is listening on 127.0.0.1:9000 then Listen() -// on ":9000" fails with the error "port already in use". -// However on Mac OSX Listen() on ":9000" falls back to the IPv6 address. -// This causes confusion on Mac OSX that minio server is not reachable -// on 127.0.0.1 even though minio server is running. So before we start -// the minio server we make sure that the port is free on each tcp network. -// -// Port is string on purpose here. -// https://github.com/golang/go/issues/16142#issuecomment-245912773 -// -// "Keep in mind that ports in Go are strings: https://play.golang.org/p/zk2WEri_E9" -// - @bradfitz -func checkPortAvailability(portStr string) error { +// checkPortAvailability - check if given port is already in use. +// Note: The check method tries to listen on given port and closes it. +// It is possible to have a disconnected client in this tiny window of time. +func checkPortAvailability(port string) error { network := [3]string{"tcp", "tcp4", "tcp6"} for _, n := range network { - l, err := net.Listen(n, net.JoinHostPort("", portStr)) + l, err := net.Listen(n, net.JoinHostPort("", port)) if err != nil { if isAddrInUse(err) { // Return error if another process is listening on the diff --git a/cmd/server-main.go b/cmd/server-main.go index 431d25a14..1971ef442 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -352,9 +352,14 @@ func getHostPort(address string) (host, port string, err error) { return "", "", err } - // Check if port is available. - if err = checkPortAvailability(port); err != nil { - return "", "", err + if runtime.GOOS == "darwin" { + // On macOS, if a process already listens on 127.0.0.1:PORT, net.Listen() falls back + // to IPv6 address ie minio will start listening on IPv6 address whereas another + // (non-)minio process is listening on IPv4 of given port. + // To avoid this error sutiation we check for port availability only for macOS. + if err = checkPortAvailability(port); err != nil { + return "", "", err + } } // Success. From 864b8795aac0d3d6e81c64ae165331be574df64e Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Mon, 30 Jan 2017 14:15:56 +0530 Subject: [PATCH 20/75] heal: Should delete stale object parts before healing (#3649) --- cmd/xl-v1-healing.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/cmd/xl-v1-healing.go b/cmd/xl-v1-healing.go index 49a03676b..1cdb9ce6f 100644 --- a/cmd/xl-v1-healing.go +++ b/cmd/xl-v1-healing.go @@ -344,22 +344,34 @@ func healObject(storageDisks []StorageAPI, bucket string, object string, quorum // Not an outdated disk. continue } - if errs[index] != nil { - // If there was an error (most likely errFileNotFound) + + // errFileNotFound implies that xl.json is missing. We + // may have object parts still present in the object + // directory. This needs to be deleted for object to + // healed successfully. + if errs[index] != nil && !isErr(errs[index], errFileNotFound) { continue } + // Outdated object with the same name exists that needs to be deleted. outDatedMeta := partsMetadata[index] - // Delete all the parts. - for partIndex := 0; partIndex < len(outDatedMeta.Parts); partIndex++ { - err := disk.DeleteFile(bucket, pathJoin(object, outDatedMeta.Parts[partIndex].Name)) - if err != nil { + // Consult valid metadata picked when there is no + // metadata available on this disk. + if isErr(errs[index], errFileNotFound) { + outDatedMeta = latestMeta + } + + // Delete all the parts. Ignore if parts are not found. + for _, part := range outDatedMeta.Parts { + err := disk.DeleteFile(bucket, pathJoin(object, part.Name)) + if err != nil && !isErr(err, errFileNotFound) { return traceError(err) } } - // Delete xl.json file. + + // Delete xl.json file. Ignore if xl.json not found. err := disk.DeleteFile(bucket, pathJoin(object, xlMetaJSONFile)) - if err != nil { + if err != nil && !isErr(err, errFileNotFound) { return traceError(err) } } From ac9ba13c19e397c18668d59568b6466ad6ed38bd Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 30 Jan 2017 01:39:53 -0800 Subject: [PATCH 21/75] build: Increase the travis build test timeout to 15mins --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cbe34000e..d6976a5b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ env: script: - make -- make test GOFLAGS="-race -v" +- make test GOFLAGS="-timeout 15m -race -v" - make coverage after_success: From 9b6bcb30d93fa05ad4f57056e597cfe7c8ad76af Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Mon, 30 Jan 2017 22:48:10 +0530 Subject: [PATCH 22/75] Fix handling of StringNotEquals condition operator (#3660) --- cmd/bucket-policy-handlers.go | 22 ++++++++++++++++++---- cmd/bucket-policy-handlers_test.go | 11 ++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index c856e38e8..6425c2df9 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -98,22 +98,32 @@ func bucketPolicyConditionMatch(conditions map[string]set.StringSet, statement p // - s3:aws-Referer for condition, conditionKeyVal := range statement.Conditions { + prefixConditon := conditionKeyVal["s3:prefix"] + maxKeyCondition := conditionKeyVal["s3:max-keys"] if condition == "StringEquals" { - if !conditionKeyVal["s3:prefix"].Equals(conditions["prefix"]) { + // If there is no condition with "s3:prefix" or "s3:max-keys" condition key + // then there is nothing to check condition against. + if !prefixConditon.IsEmpty() && !prefixConditon.Equals(conditions["prefix"]) { return false } - if !conditionKeyVal["s3:max-keys"].Equals(conditions["max-keys"]) { + if !maxKeyCondition.IsEmpty() && !maxKeyCondition.Equals(conditions["max-keys"]) { return false } } else if condition == "StringNotEquals" { - if !conditionKeyVal["s3:prefix"].Equals(conditions["prefix"]) { + // If there is no condition with "s3:prefix" or "s3:max-keys" condition key + // then there is nothing to check condition against. + if !prefixConditon.IsEmpty() && prefixConditon.Equals(conditions["prefix"]) { return false } - if !conditionKeyVal["s3:max-keys"].Equals(conditions["max-keys"]) { + if !maxKeyCondition.IsEmpty() && maxKeyCondition.Equals(conditions["max-keys"]) { return false } } else if condition == "StringLike" { awsReferers := conditionKeyVal["aws:Referer"] + // Skip empty condition, it is trivially satisfied. + if awsReferers.IsEmpty() { + continue + } // wildcard match of referer in statement was not empty. // StringLike has a match, i.e, condition evaluates to true. for referer := range conditions["referer"] { @@ -125,6 +135,10 @@ func bucketPolicyConditionMatch(conditions map[string]set.StringSet, statement p return false } else if condition == "StringNotLike" { awsReferers := conditionKeyVal["aws:Referer"] + // Skip empty condition, it is trivially satisfied. + if awsReferers.IsEmpty() { + continue + } // wildcard match of referer in statement was not empty. // StringNotLike has a match, i.e, condition evaluates to false. for referer := range conditions["referer"] { diff --git a/cmd/bucket-policy-handlers_test.go b/cmd/bucket-policy-handlers_test.go index 999dc5530..a8ad8a3e1 100644 --- a/cmd/bucket-policy-handlers_test.go +++ b/cmd/bucket-policy-handlers_test.go @@ -913,7 +913,7 @@ func TestBucketPolicyConditionMatch(t *testing.T) { statementCondition: getStatementWithCondition("StringNotEquals", "s3:prefix", "Asia/"), condition: getInnerMap("prefix", "Asia/"), - expectedMatch: true, + expectedMatch: false, }, // Test case - 6. // StringNotEquals condition doesn't match. @@ -922,7 +922,7 @@ func TestBucketPolicyConditionMatch(t *testing.T) { statementCondition: getStatementWithCondition("StringNotEquals", "s3:prefix", "Asia/"), condition: getInnerMap("prefix", "Africa/"), - expectedMatch: false, + expectedMatch: true, }, // Test case - 7. // StringNotEquals condition matches. @@ -931,7 +931,7 @@ func TestBucketPolicyConditionMatch(t *testing.T) { statementCondition: getStatementWithCondition("StringNotEquals", "s3:max-keys", "Asia/"), condition: getInnerMap("max-keys", "Asia/"), - expectedMatch: true, + expectedMatch: false, }, // Test case - 8. // StringNotEquals condition doesn't match. @@ -940,7 +940,7 @@ func TestBucketPolicyConditionMatch(t *testing.T) { statementCondition: getStatementWithCondition("StringNotEquals", "s3:max-keys", "Asia/"), condition: getInnerMap("max-keys", "Africa/"), - expectedMatch: false, + expectedMatch: true, }, // Test case - 9. // StringLike condition matches. @@ -977,7 +977,8 @@ func TestBucketPolicyConditionMatch(t *testing.T) { // call the function under test and assert the result with the expected result. doesMatch := bucketPolicyConditionMatch(tc.condition, tc.statementCondition) if tc.expectedMatch != doesMatch { - t.Errorf("Expected the match to be `%v`; got `%v`.", tc.expectedMatch, doesMatch) + t.Errorf("Expected the match to be `%v`; got `%v` - %v %v.", + tc.expectedMatch, doesMatch, tc.condition, tc.statementCondition) } }) } From 2665aba55525f47faf8a362d21b2aa1da10e09fa Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Mon, 30 Jan 2017 22:50:16 +0530 Subject: [PATCH 23/75] Fail PutBucketPolicy if conditions are incompatible with actions. (#3659) --- cmd/bucket-policy-handlers.go | 15 +++++++++----- cmd/bucket-policy-parser.go | 31 ++++++++++++++++++++-------- cmd/bucket-policy-parser_test.go | 35 +++++++++++++++++--------------- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index 6425c2df9..00b3b5d2b 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -97,6 +97,9 @@ func bucketPolicyConditionMatch(conditions map[string]set.StringSet, statement p // - s3:max-keys // - s3:aws-Referer + // The following loop evaluates the logical AND of all the + // conditions in the statement. Note: we can break out of the + // loop if and only if a condition evaluates to false. for condition, conditionKeyVal := range statement.Conditions { prefixConditon := conditionKeyVal["s3:prefix"] maxKeyCondition := conditionKeyVal["s3:max-keys"] @@ -126,13 +129,17 @@ func bucketPolicyConditionMatch(conditions map[string]set.StringSet, statement p } // wildcard match of referer in statement was not empty. // StringLike has a match, i.e, condition evaluates to true. + refererFound := false for referer := range conditions["referer"] { if !awsReferers.FuncMatch(refererMatch, referer).IsEmpty() { - return true + refererFound = true + break } } // No matching referer found, so the condition is false. - return false + if !refererFound { + return false + } } else if condition == "StringNotLike" { awsReferers := conditionKeyVal["aws:Referer"] // Skip empty condition, it is trivially satisfied. @@ -146,11 +153,9 @@ func bucketPolicyConditionMatch(conditions map[string]set.StringSet, statement p return false } } - // No matching referer found, so the condition is true. - return true } } - // No conditions were present in the statement, so trivially true (always). + return true } diff --git a/cmd/bucket-policy-parser.go b/cmd/bucket-policy-parser.go index f9324846c..7af5e5bf4 100644 --- a/cmd/bucket-policy-parser.go +++ b/cmd/bucket-policy-parser.go @@ -29,6 +29,11 @@ import ( "github.com/minio/minio-go/pkg/set" ) +var conditionKeyActionMap = map[string]set.StringSet{ + "s3:prefix": set.CreateStringSet("s3:ListBucket"), + "s3:max-keys": set.CreateStringSet("s3:ListBucket"), +} + // supportedActionMap - lists all the actions supported by minio. var supportedActionMap = set.CreateStringSet("*", "s3:*", "s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:GetBucketLocation", "s3:DeleteObject", @@ -178,11 +183,12 @@ func isValidPrincipals(principal interface{}) (err error) { return nil } -// isValidConditions - are valid conditions. -func isValidConditions(conditions map[string]map[string]set.StringSet) (err error) { - // Verify conditions should be valid. - // Validate if stringEquals, stringNotEquals are present - // if not throw an error. +// isValidConditions - returns nil if the given conditions valid and +// corresponding error otherwise. +func isValidConditions(actions set.StringSet, conditions map[string]map[string]set.StringSet) (err error) { + // Verify conditions should be valid. Validate if only + // supported condition keys are present and return error + // otherwise. conditionKeyVal := make(map[string]set.StringSet) for conditionType := range conditions { if !supportedConditionsType.Contains(conditionType) { @@ -194,6 +200,15 @@ func isValidConditions(conditions map[string]map[string]set.StringSet) (err erro err = fmt.Errorf("Unsupported condition key '%s', please validate your policy document", conditionType) return err } + + compatibleActions := conditionKeyActionMap[key] + if !compatibleActions.IsEmpty() && + compatibleActions.Intersection(actions).IsEmpty() { + err = fmt.Errorf("Unsupported condition key %s for the given actions %s, "+ + "please validate your policy document", key, actions) + return err + } + conditionVal, ok := conditionKeyVal[key] if ok && !value.Intersection(conditionVal).IsEmpty() { err = fmt.Errorf("Ambigious condition values for key '%s', please validate your policy document", key) @@ -222,8 +237,8 @@ func resourcePrefix(resource string) string { } // checkBucketPolicyResources validates Resources in unmarshalled bucket policy structure. -// First valation of Resources done for given set of Actions. -// Later its validated for recursive Resources. +// - Resources are validated against the given set of Actions. +// - func checkBucketPolicyResources(bucket string, bucketPolicy *bucketPolicy) APIErrorCode { // Validate statements for special actions and collect resources // for others to validate nesting. @@ -317,7 +332,7 @@ func parseBucketPolicy(bucketPolicyReader io.Reader, policy *bucketPolicy) (err return err } // Statement conditions should be valid. - if err := isValidConditions(statement.Conditions); err != nil { + if err := isValidConditions(statement.Actions, statement.Conditions); err != nil { return err } } diff --git a/cmd/bucket-policy-parser_test.go b/cmd/bucket-policy-parser_test.go index a9418db1f..a712a30c4 100644 --- a/cmd/bucket-policy-parser_test.go +++ b/cmd/bucket-policy-parser_test.go @@ -433,7 +433,12 @@ func TestIsValidConditions(t *testing.T) { generateConditions("StringNotEquals", "s3:max-keys", "100"), } + getObjectActionSet := set.CreateStringSet("s3:GetObject") + roBucketActionSet := set.CreateStringSet(readOnlyBucketActions...) + maxKeysConditionErr := fmt.Errorf("Unsupported condition key %s for the given actions %s, "+ + "please validate your policy document", "s3:max-keys", getObjectActionSet) testCases := []struct { + inputActions set.StringSet inputCondition map[string]map[string]set.StringSet // expected result. expectedErr error @@ -443,46 +448,44 @@ func TestIsValidConditions(t *testing.T) { // Malformed conditions. // Test case - 1. // "StringValues" is an invalid type. - {testConditions[0], fmt.Errorf("Unsupported condition type 'StringValues', " + + {roBucketActionSet, testConditions[0], fmt.Errorf("Unsupported condition type 'StringValues', " + "please validate your policy document"), false}, // Test case - 2. // "s3:Object" is an invalid key. - {testConditions[1], fmt.Errorf("Unsupported condition key " + + {roBucketActionSet, testConditions[1], fmt.Errorf("Unsupported condition key " + "'StringEquals', please validate your policy document"), false}, // Test case - 3. // Test case with Ambigious conditions set. - {testConditions[2], fmt.Errorf("Ambigious condition values for key 's3:prefix', " + + {roBucketActionSet, testConditions[2], fmt.Errorf("Ambigious condition values for key 's3:prefix', " + "please validate your policy document"), false}, // Test case - 4. // Test case with valid and invalid condition types. - {testConditions[3], fmt.Errorf("Unsupported condition type 'InvalidType', " + + {roBucketActionSet, testConditions[3], fmt.Errorf("Unsupported condition type 'InvalidType', " + "please validate your policy document"), false}, // Test case - 5. // Test case with valid and invalid condition keys. - {testConditions[4], fmt.Errorf("Unsupported condition key 'StringEquals', " + + {roBucketActionSet, testConditions[4], fmt.Errorf("Unsupported condition key 'StringEquals', " + "please validate your policy document"), false}, // Test cases with valid conditions. // Test case - 6. - {testConditions[5], nil, true}, + {roBucketActionSet, testConditions[5], nil, true}, // Test case - 7. - {testConditions[6], nil, true}, + {roBucketActionSet, testConditions[6], nil, true}, // Test case - 8. - {testConditions[7], nil, true}, + {roBucketActionSet, testConditions[7], nil, true}, // Test case - 9. - {testConditions[8], nil, true}, + {roBucketActionSet, testConditions[8], nil, true}, // Test case - 10. - {testConditions[9], nil, true}, + {roBucketActionSet, testConditions[9], nil, true}, // Test case - 11. - {testConditions[10], nil, true}, + {roBucketActionSet, testConditions[10], nil, true}, // Test case - 12. - {testConditions[11], nil, true}, + {roBucketActionSet, testConditions[11], nil, true}, // Test case - 13. - {testConditions[11], nil, true}, - // Test case - 14. - {testConditions[11], nil, true}, + {getObjectActionSet, testConditions[11], maxKeysConditionErr, false}, } for i, testCase := range testCases { - actualErr := isValidConditions(testCase.inputCondition) + actualErr := isValidConditions(testCase.inputActions, testCase.inputCondition) if actualErr != nil && testCase.shouldPass { t.Errorf("Test %d: Expected to pass, but failed with: %s", i+1, actualErr.Error()) } From b288eaddb30bcecf2f033d1a550f8f72f06acde9 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Mon, 30 Jan 2017 14:25:28 -0800 Subject: [PATCH 24/75] xl: bit-rot algo was not set in get-object. (#3652) fixes #3650 --- cmd/xl-v1-object.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index b3ea9b2ff..a55e31306 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -287,7 +287,7 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i // Set checksum algo only once, while it is possible to have // different algos per block because of our `xl.json`. // It is not a requirement, set this only once for all the disks. - if ckSumAlgo != "" { + if ckSumAlgo == "" { ckSumAlgo = ckSumInfo.Algorithm } } From 46743c7918d9cecc0179c7cbcf579a5f8606dfaf Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Mon, 30 Jan 2017 14:25:55 -0800 Subject: [PATCH 25/75] browser: Component attr names should not clash with redux state keys. (#3656) fixes #270 --- browser/app/js/components/Browse.js | 8 ++++---- browser/app/js/components/BrowserDropdown.js | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/browser/app/js/components/Browse.js b/browser/app/js/components/Browse.js index 671552529..4c2343762 100644 --- a/browser/app/js/components/Browse.js +++ b/browser/app/js/components/Browse.js @@ -414,10 +414,10 @@ export default class Browse extends React.Component { let freePercent = free * 100 / total if (web.LoggedIn()) { - browserDropdownButton = + browserDropdownButton = } else { loginButton = Login } diff --git a/browser/app/js/components/BrowserDropdown.js b/browser/app/js/components/BrowserDropdown.js index 1aa272551..171e6f3e7 100644 --- a/browser/app/js/components/BrowserDropdown.js +++ b/browser/app/js/components/BrowserDropdown.js @@ -18,7 +18,7 @@ import React from 'react' import connect from 'react-redux/lib/components/connect' import Dropdown from 'react-bootstrap/lib/Dropdown' -let BrowserDropdown = ({fullScreen, showAbout, showSettings, logout}) => { +let BrowserDropdown = ({fullScreenFunc, aboutFunc, settingsFunc, logoutFunc}) => { return (
  • @@ -30,7 +30,7 @@ let BrowserDropdown = ({fullScreen, showAbout, showSettings, logout}) => { Github
  • - Fullscreen + Fullscreen
  • Documentation @@ -39,13 +39,13 @@ let BrowserDropdown = ({fullScreen, showAbout, showSettings, logout}) => { Ask for help
  • - About + About
  • - Settings + Settings
  • - Sign Out + Sign Out
  • From e9394dc22df31cdf3ecb63897204ca51b95852a8 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Tue, 31 Jan 2017 00:44:42 +0100 Subject: [PATCH 26/75] xl PutObject: Split object into parts (#3651) For faster time-to-first-byte when we try to download a big object --- cmd/api-errors.go | 5 ++ cmd/erasure-createfile.go | 4 +- cmd/erasure-createfile_test.go | 8 +-- cmd/erasure-healfile_test.go | 2 +- cmd/erasure-readfile_test.go | 6 +- cmd/globals.go | 3 + cmd/xl-v1-multipart.go | 5 +- cmd/xl-v1-object.go | 118 ++++++++++++++++++++++++--------- cmd/xl-v1-utils.go | 27 ++++++++ cmd/xl-v1-utils_test.go | 34 ++++++++++ 10 files changed, 169 insertions(+), 43 deletions(-) diff --git a/cmd/api-errors.go b/cmd/api-errors.go index 8021b8098..ed7529560 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -606,6 +606,11 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) { apiErr = ErrSignatureDoesNotMatch case errContentSHA256Mismatch: apiErr = ErrContentSHA256Mismatch + case errDataTooLarge: + apiErr = ErrEntityTooLarge + case errDataTooSmall: + apiErr = ErrEntityTooSmall + } if apiErr != ErrNone { diff --git a/cmd/erasure-createfile.go b/cmd/erasure-createfile.go index 18797ba5f..d20ca8060 100644 --- a/cmd/erasure-createfile.go +++ b/cmd/erasure-createfile.go @@ -28,7 +28,7 @@ import ( // erasureCreateFile - writes an entire stream by erasure coding to // all the disks, writes also calculate individual block's checksum // for future bit-rot protection. -func erasureCreateFile(disks []StorageAPI, volume, path string, reader io.Reader, blockSize int64, dataBlocks int, parityBlocks int, algo string, writeQuorum int) (bytesWritten int64, checkSums []string, err error) { +func erasureCreateFile(disks []StorageAPI, volume, path string, reader io.Reader, allowEmpty bool, blockSize int64, dataBlocks int, parityBlocks int, algo string, writeQuorum int) (bytesWritten int64, checkSums []string, err error) { // Allocated blockSized buffer for reading from incoming stream. buf := make([]byte, blockSize) @@ -47,7 +47,7 @@ func erasureCreateFile(disks []StorageAPI, volume, path string, reader io.Reader // We have reached EOF on the first byte read, io.Reader // must be 0bytes, we don't need to erasure code // data. Will create a 0byte file instead. - if bytesWritten == 0 { + if bytesWritten == 0 && allowEmpty { blocks = make([][]byte, len(disks)) rErr = appendFile(disks, volume, path, blocks, hashWriters, writeQuorum) if rErr != nil { diff --git a/cmd/erasure-createfile_test.go b/cmd/erasure-createfile_test.go index 2411bd432..bcc9973eb 100644 --- a/cmd/erasure-createfile_test.go +++ b/cmd/erasure-createfile_test.go @@ -56,7 +56,7 @@ func TestErasureCreateFile(t *testing.T) { t.Fatal(err) } // Test when all disks are up. - size, _, err := erasureCreateFile(disks, "testbucket", "testobject1", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, _, err := erasureCreateFile(disks, "testbucket", "testobject1", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } @@ -69,7 +69,7 @@ func TestErasureCreateFile(t *testing.T) { disks[5] = AppendDiskDown{disks[5].(*posix)} // Test when two disks are down. - size, _, err = erasureCreateFile(disks, "testbucket", "testobject2", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, _, err = erasureCreateFile(disks, "testbucket", "testobject2", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } @@ -83,7 +83,7 @@ func TestErasureCreateFile(t *testing.T) { disks[8] = AppendDiskDown{disks[8].(*posix)} disks[9] = AppendDiskDown{disks[9].(*posix)} - size, _, err = erasureCreateFile(disks, "testbucket", "testobject3", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, _, err = erasureCreateFile(disks, "testbucket", "testobject3", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } @@ -93,7 +93,7 @@ func TestErasureCreateFile(t *testing.T) { // 1 more disk down. 7 disk down in total. Should return quorum error. disks[10] = AppendDiskDown{disks[10].(*posix)} - _, _, err = erasureCreateFile(disks, "testbucket", "testobject4", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + _, _, err = erasureCreateFile(disks, "testbucket", "testobject4", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if errorCause(err) != errXLWriteQuorum { t.Errorf("erasureCreateFile return value: expected errXLWriteQuorum, got %s", err) } diff --git a/cmd/erasure-healfile_test.go b/cmd/erasure-healfile_test.go index b4e644c07..0f820738c 100644 --- a/cmd/erasure-healfile_test.go +++ b/cmd/erasure-healfile_test.go @@ -48,7 +48,7 @@ func TestErasureHealFile(t *testing.T) { t.Fatal(err) } // Create a test file. - size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject1", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject1", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } diff --git a/cmd/erasure-readfile_test.go b/cmd/erasure-readfile_test.go index ab0e8f947..51071952f 100644 --- a/cmd/erasure-readfile_test.go +++ b/cmd/erasure-readfile_test.go @@ -271,7 +271,7 @@ func TestErasureReadFileDiskFail(t *testing.T) { } // Create a test file to read from. - size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } @@ -354,7 +354,7 @@ func TestErasureReadFileOffsetLength(t *testing.T) { } // Create a test file to read from. - size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } @@ -433,7 +433,7 @@ func TestErasureReadFileRandomOffsetLength(t *testing.T) { iterations := 10000 // Create a test file to read from. - size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject", bytes.NewReader(data), blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) + size, checkSums, err := erasureCreateFile(disks, "testbucket", "testobject", bytes.NewReader(data), true, blockSize, dataBlocks, parityBlocks, bitRotAlgo, dataBlocks+1) if err != nil { t.Fatal(err) } diff --git a/cmd/globals.go b/cmd/globals.go index 4eed8972b..f2ed99dd9 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -82,6 +82,9 @@ var ( // Caching is enabled only for RAM size > 8GiB. globalMaxCacheSize = uint64(0) + // Maximum size of internal objects parts + globalPutPartSize = int64(64 * 1024 * 1024) + // Cache expiry. globalCacheExpiry = objcache.DefaultExpiry diff --git a/cmd/xl-v1-multipart.go b/cmd/xl-v1-multipart.go index 92fafc35e..10fd79f1f 100644 --- a/cmd/xl-v1-multipart.go +++ b/cmd/xl-v1-multipart.go @@ -627,8 +627,11 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s } } + // We always allow empty part. + allowEmpty := true + // Erasure code data and write across all disks. - sizeWritten, checkSums, err := erasureCreateFile(onlineDisks, minioMetaTmpBucket, tmpPartPath, teeReader, xlMeta.Erasure.BlockSize, xl.dataBlocks, xl.parityBlocks, bitRotAlgo, xl.writeQuorum) + sizeWritten, checkSums, err := erasureCreateFile(onlineDisks, minioMetaTmpBucket, tmpPartPath, teeReader, allowEmpty, xlMeta.Erasure.BlockSize, xl.dataBlocks, xl.parityBlocks, bitRotAlgo, xl.writeQuorum) if err != nil { return "", toObjectErr(err, bucket, object) } diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index a55e31306..86563d362 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -22,6 +22,7 @@ import ( "hash" "io" "path" + "strconv" "strings" "sync" "time" @@ -461,7 +462,6 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. } uniqueID := mustGetUUID() - tempErasureObj := path.Join(uniqueID, "part.1") tempObj := uniqueID // Initialize md5 writer. @@ -512,40 +512,101 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. // Tee reader combines incoming data stream and md5, data read from input stream is written to md5. teeReader := io.TeeReader(limitDataReader, mw) - // Initialize xl meta. + // Initialize parts metadata + partsMetadata := make([]xlMetaV1, len(xl.storageDisks)) + xlMeta := newXLMetaV1(object, xl.dataBlocks, xl.parityBlocks) - onlineDisks := getOrderedDisks(xlMeta.Erasure.Distribution, xl.storageDisks) + // Initialize xl meta. + for index := range partsMetadata { + partsMetadata[index] = xlMeta + } + + // Order disks according to erasure distribution + onlineDisks := getOrderedDisks(partsMetadata[0].Erasure.Distribution, xl.storageDisks) // Delete temporary object in the event of failure. // If PutObject succeeded there would be no temporary // object to delete. defer xl.deleteObject(minioMetaTmpBucket, tempObj) - if size > 0 { - for _, disk := range onlineDisks { - if disk != nil { - actualSize := xl.sizeOnDisk(size, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks) - disk.PrepareFile(minioMetaTmpBucket, tempErasureObj, actualSize) + // Total size of the written object + sizeWritten := int64(0) + + // Read data and split into parts - similar to multipart mechanism + for partIdx := 1; ; partIdx++ { + // Compute part name + partName := "part." + strconv.Itoa(partIdx) + // Compute the path of current part + tempErasureObj := path.Join(uniqueID, partName) + + // Calculate the size of the current part, if size is unknown, curPartSize wil be unknown too. + // allowEmptyPart will always be true if this is the first part and false otherwise. + curPartSize := getPartSizeFromIdx(size, globalPutPartSize, partIdx) + + // Prepare file for eventual optimization in the disk + if curPartSize > 0 { + // Calculate the real size of the part in the disk and prepare it for eventual optimization + actualSize := xl.sizeOnDisk(curPartSize, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks) + for _, disk := range onlineDisks { + if disk != nil { + disk.PrepareFile(minioMetaTmpBucket, tempErasureObj, actualSize) + } } } - } - // Erasure code data and write across all disks. - sizeWritten, checkSums, err := erasureCreateFile(onlineDisks, minioMetaTmpBucket, tempErasureObj, teeReader, xlMeta.Erasure.BlockSize, xlMeta.Erasure.DataBlocks, xlMeta.Erasure.ParityBlocks, bitRotAlgo, xl.writeQuorum) - if err != nil { - return ObjectInfo{}, toObjectErr(err, minioMetaTmpBucket, tempErasureObj) - } - // Should return IncompleteBody{} error when reader has fewer bytes - // than specified in request header. - if sizeWritten < size { - return ObjectInfo{}, traceError(IncompleteBody{}) + // partReader streams at most maximum part size + partReader := io.LimitReader(teeReader, globalPutPartSize) + + // Allow creating empty earsure file only when this is the first part. This flag is useful + // when size == -1 because in this case, we are not able to predict how many parts we will have. + allowEmptyPart := partIdx == 1 + + // Erasure code data and write across all disks. + partSizeWritten, checkSums, erasureErr := erasureCreateFile(onlineDisks, minioMetaTmpBucket, tempErasureObj, partReader, allowEmptyPart, partsMetadata[0].Erasure.BlockSize, partsMetadata[0].Erasure.DataBlocks, partsMetadata[0].Erasure.ParityBlocks, bitRotAlgo, xl.writeQuorum) + if erasureErr != nil { + return ObjectInfo{}, toObjectErr(erasureErr, minioMetaTmpBucket, tempErasureObj) + } + + // Should return IncompleteBody{} error when reader has fewer bytes + // than specified in request header. + if partSizeWritten < int64(curPartSize) { + return ObjectInfo{}, traceError(IncompleteBody{}) + } + + // Update the total written size + sizeWritten += partSizeWritten + + // If erasure stored some data in the loop or created an empty file + if partSizeWritten > 0 || allowEmptyPart { + for index := range partsMetadata { + // Add the part to xl.json. + partsMetadata[index].AddObjectPart(partIdx, partName, "", partSizeWritten) + // Add part checksum info to xl.json. + partsMetadata[index].Erasure.AddCheckSumInfo(checkSumInfo{ + Name: partName, + Hash: checkSums[index], + Algorithm: bitRotAlgo, + }) + } + } + + // If we didn't write anything or we know that the next part doesn't have any + // data to write, we should quit this loop immediately + if partSizeWritten == 0 || getPartSizeFromIdx(size, globalPutPartSize, partIdx+1) == 0 { + break + } } // For size == -1, perhaps client is sending in chunked encoding // set the size as size that was actually written. if size == -1 { size = sizeWritten + } else { + // Check if stored data satisfies what is asked + if sizeWritten < size { + return ObjectInfo{}, traceError(IncompleteBody{}) + } } // Save additional erasureMetadata. @@ -604,22 +665,11 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. } // Fill all the necessary metadata. - xlMeta.Meta = metadata - xlMeta.Stat.Size = size - xlMeta.Stat.ModTime = modTime - - // Add the final part. - xlMeta.AddObjectPart(1, "part.1", newMD5Hex, xlMeta.Stat.Size) - - partsMetadata := make([]xlMetaV1, len(xl.storageDisks)) // Update `xl.json` content on each disks. for index := range partsMetadata { - partsMetadata[index] = xlMeta - partsMetadata[index].Erasure.AddCheckSumInfo(checkSumInfo{ - Name: "part.1", - Hash: checkSums[index], - Algorithm: bitRotAlgo, - }) + partsMetadata[index].Meta = metadata + partsMetadata[index].Stat.Size = size + partsMetadata[index].Stat.ModTime = modTime } // Write unique `xl.json` for each disk. @@ -639,6 +689,10 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. newBuffer.Close() } + // Object info is the same in all disks, so we can pick the first meta + // of the first disk + xlMeta = partsMetadata[0] + objInfo = ObjectInfo{ IsDir: false, Bucket: bucket, diff --git a/cmd/xl-v1-utils.go b/cmd/xl-v1-utils.go index e2309483c..536eae968 100644 --- a/cmd/xl-v1-utils.go +++ b/cmd/xl-v1-utils.go @@ -343,3 +343,30 @@ func getOrderedDisks(distribution []int, disks []StorageAPI) (orderedDisks []Sto } return orderedDisks } + +// getPartSizeFromIdx predicts the part size according to its index. It also +// returns -1 when totalSize is also -1. +func getPartSizeFromIdx(totalSize int64, partSize int64, partIndex int) int64 { + if partSize == 0 { + panic("Part size cannot be nil.") + } + if partIndex < 1 { + panic("Part index should be greater than 1.") + } + switch totalSize { + case -1, 0: + return totalSize + } + // Compute the total count of parts + partsCount := totalSize/partSize + 1 + // Return the part's size + switch { + case int64(partIndex) < partsCount: + return partSize + case int64(partIndex) == partsCount: + // Size of last part + return totalSize % partSize + default: + return 0 + } +} diff --git a/cmd/xl-v1-utils_test.go b/cmd/xl-v1-utils_test.go index 1bada5408..4b80ffbb4 100644 --- a/cmd/xl-v1-utils_test.go +++ b/cmd/xl-v1-utils_test.go @@ -22,6 +22,8 @@ import ( "strconv" "testing" "time" + + humanize "github.com/dustin/go-humanize" ) // Tests caclculating disk count. @@ -325,3 +327,35 @@ func TestGetXLMetaV1GJson10(t *testing.T) { } compareXLMetaV1(t, unMarshalXLMeta, gjsonXLMeta) } + +// Test the predicted part size from the part index +func TestGetPartSizeFromIdx(t *testing.T) { + // Create test cases + testCases := []struct { + totalSize int64 + partSize int64 + partIndex int + expectedSize int64 + }{ + // Total size is - 1 + {-1, 10, 1, -1}, + // Total size is zero + {0, 10, 1, 0}, + // part size 2MiB, total size 4MiB + {4 * humanize.MiByte, 2 * humanize.MiByte, 1, 2 * humanize.MiByte}, + {4 * humanize.MiByte, 2 * humanize.MiByte, 2, 2 * humanize.MiByte}, + {4 * humanize.MiByte, 2 * humanize.MiByte, 3, 0}, + // part size 2MiB, total size 5MiB + {5 * humanize.MiByte, 2 * humanize.MiByte, 1, 2 * humanize.MiByte}, + {5 * humanize.MiByte, 2 * humanize.MiByte, 2, 2 * humanize.MiByte}, + {5 * humanize.MiByte, 2 * humanize.MiByte, 3, 1 * humanize.MiByte}, + {5 * humanize.MiByte, 2 * humanize.MiByte, 4, 0}, + } + + for i, testCase := range testCases { + s := getPartSizeFromIdx(testCase.totalSize, testCase.partSize, testCase.partIndex) + if s != testCase.expectedSize { + t.Errorf("Test %d: The calculated part size is incorrect: expected = %d, found = %d\n", i+1, testCase.expectedSize, s) + } + } +} From cb48517a78f34fbc3a6cfcf625e813abd9f9ee70 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 30 Jan 2017 16:38:49 -0800 Subject: [PATCH 27/75] Update browser assets with new changes. --- browser/ui-assets.go | 50 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/browser/ui-assets.go b/browser/ui-assets.go index fdceb7cbb..b8c898e5a 100644 --- a/browser/ui-assets.go +++ b/browser/ui-assets.go @@ -4,7 +4,7 @@ // production/favicon.ico // production/firefox.png // production/index.html -// production/index_bundle-2017-01-25T03-10-51Z.js +// production/index_bundle-2017-01-31T00-38-09Z.js // production/loader.css // production/logo.svg // production/safari.png @@ -65,7 +65,7 @@ func productionChromePng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -82,7 +82,7 @@ func productionFaviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -99,7 +99,7 @@ func productionFirefoxPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -156,8 +156,8 @@ var _productionIndexHTML = []byte(` - - + + `) @@ -172,12 +172,12 @@ func productionIndexHTML() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _productionIndex_bundle20170125t031051zJs = []byte(`!function(A){function M(I){if(t[I])return t[I].exports;var g=t[I]={exports:{},id:I,loaded:!1};return A[I].call(g.exports,g,g.exports,M),g.loaded=!0,g.exports}var t={};return M.m=A,M.c=t,M.p="",M(0)}([function(A,M,t){A.exports=t(240)},function(A,M,t){"use strict";A.exports=t(439)},function(A,M,t){"use strict";function I(A,M,t,I,g,e,i,T){if(!A){var E;if(void 0===M)E=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var N=[t,I,g,e,i,T],o=0;E=new Error(M.replace(/%s/g,function(){return N[o++]})),E.name="Invariant Violation"}throw E.framesToPop=1,E}}A.exports=I},function(A,M,t){"use strict";var I=t(20),g=I;A.exports=g},function(A,M){"use strict";function t(A,M){if(null==A)throw new TypeError("Object.assign target cannot be null or undefined");for(var t=Object(A),I=Object.prototype.hasOwnProperty,g=1;gM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;iM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;i-1&&A%1==0&&A1)for(var t=1;tA.clientHeight}Object.defineProperty(M,"__esModule",{value:!0}),M.default=i;var T=t(57),E=I(T),N=t(39),o=I(N);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):"function"!==E&&"string"!==E?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):null}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M){"use strict";function t(A){function M(M,t,I,g,e,i){var T=g||"<>",E=i||I;if(null==t[I])return M?new Error("Required "+e+" ` + "`" + `"+E+"` + "`" + ` was not specified "+("in ` + "`" + `"+T+"` + "`" + `.")):null;for(var N=arguments.length,o=Array(N>6?N-6:0),n=6;n=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return 0===A.button}function i(A){return!!(A.metaKey||A.altKey||A.ctrlKey||A.shiftKey)}function T(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!1;return!0}function E(A,M){var t=M.query,I=M.hash,g=M.state;return t||I||g?{pathname:A,query:t,hash:I,state:g}:A}M.__esModule=!0;var N=Object.assign||function(A){for(var M=1;M=0;I--){var g=A[I],e=g.path||"";if(t=e.replace(/\/*$/,"/")+t,0===e.indexOf("/"))break}return"/"+t}},propTypes:{path:C,from:C,to:C.isRequired,query:c,state:c,onEnter:o.falsy,children:o.falsy},render:function(){(0,T.default)(!1)}});M.default=D,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0;var g=t(1),e=I(g),i=t(8),T=I(i),E=t(30),N=t(34),o=e.default.PropTypes,n=o.string,C=o.func,c=e.default.createClass({displayName:"Route",statics:{createRouteFromReactElement:E.createRouteFromReactElement},propTypes:{path:n,component:N.component,components:N.components,getComponent:C,getComponents:C},render:function(){(0,T.default)(!1)}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return!A||!A.__v2_compatible__}function i(A){return A&&A.getCurrentLocation}M.__esModule=!0;var T=Object.assign||function(A){for(var M=1;M=0&&0===window.sessionStorage.length)return;throw A}}function i(A){var M=void 0;try{M=window.sessionStorage.getItem(g(A))}catch(A){if(A.name===o)return null}if(M)try{return JSON.parse(M)}catch(A){}return null}M.__esModule=!0,M.saveState=e,M.readState=i;var T=t(23),E=(I(T),"@@History/"),N=["QuotaExceededError","QUOTA_EXCEEDED_ERR"],o="SecurityError"},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){function M(A){return E.canUseDOM?void 0:T.default(!1),t.listen(A)}var t=n.default(e({getUserConfirmation:N.getUserConfirmation},A,{go:N.go}));return e({},t,{listen:M})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M1?M-1:0),e=1;e=A.childNodes.length?null:A.childNodes.item(t);A.insertBefore(M,I)}var g=t(433),e=t(220),i=t(17),T=t(76),E=t(121),N=t(2),o={dangerouslyReplaceNodeWithMarkup:g.dangerouslyReplaceNodeWithMarkup,updateTextContent:E,processUpdates:function(A,M){for(var t,i=null,o=null,n=0;n-1?void 0:i(!1),!N.plugins[t]){M.extractEvents?void 0:i(!1),N.plugins[t]=M;var I=M.eventTypes;for(var e in I)g(I[e],M,e)?void 0:i(!1)}}}function g(A,M,t){N.eventNameDispatchConfigs.hasOwnProperty(t)?i(!1):void 0,N.eventNameDispatchConfigs[t]=A;var I=A.phasedRegistrationNames;if(I){for(var g in I)if(I.hasOwnProperty(g)){var T=I[g];e(T,M,t)}return!0}return!!A.registrationName&&(e(A.registrationName,M,t),!0)}function e(A,M,t){N.registrationNameModules[A]?i(!1):void 0,N.registrationNameModules[A]=M,N.registrationNameDependencies[A]=M.eventTypes[t].dependencies}var i=t(2),T=null,E={},N={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(A){T?i(!1):void 0,T=Array.prototype.slice.call(A),I()},injectEventPluginsByName:function(A){var M=!1;for(var t in A)if(A.hasOwnProperty(t)){var g=A[t];E.hasOwnProperty(t)&&E[t]===g||(E[t]?i(!1):void 0,E[t]=g,M=!0)}M&&I()},getPluginModuleForEvent:function(A){var M=A.dispatchConfig;if(M.registrationName)return N.registrationNameModules[M.registrationName]||null;for(var t in M.phasedRegistrationNames)if(M.phasedRegistrationNames.hasOwnProperty(t)){var I=N.registrationNameModules[M.phasedRegistrationNames[t]];if(I)return I}return null},_resetEventPlugins:function(){T=null;for(var A in E)E.hasOwnProperty(A)&&delete E[A];N.plugins.length=0;var M=N.eventNameDispatchConfigs;for(var t in M)M.hasOwnProperty(t)&&delete M[t];var I=N.registrationNameModules;for(var g in I)I.hasOwnProperty(g)&&delete I[g]}};A.exports=N},function(A,M,t){"use strict";function I(A){return(""+A).replace(x,"//")}function g(A,M){this.func=A,this.context=M,this.count=0}function e(A,M,t){var I=A.func,g=A.context;I.call(g,M,A.count++)}function i(A,M,t){if(null==A)return A;var I=g.getPooled(M,t);Q(A,e,I),g.release(I)}function T(A,M,t,I){this.result=A,this.keyPrefix=M,this.func=t,this.context=I,this.count=0}function E(A,M,t){var g=A.result,e=A.keyPrefix,i=A.func,T=A.context,E=i.call(T,M,A.count++);Array.isArray(E)?N(E,g,t,B.thatReturnsArgument):null!=E&&(a.isValidElement(E)&&(E=a.cloneAndReplaceKey(E,e+(E!==M?I(E.key||"")+"/":"")+t)),g.push(E))}function N(A,M,t,g,e){var i="";null!=t&&(i=I(t)+"/");var N=T.getPooled(M,i,g,e);Q(A,E,N),T.release(N)}function o(A,M,t){if(null==A)return A;var I=[];return N(A,I,null,M,t),I}function n(A,M,t){return null}function C(A,M){return Q(A,n,null)}function c(A){var M=[];return N(A,M,null,B.thatReturnsArgument),M}var D=t(31),a=t(13),B=t(20),Q=t(123),r=D.twoArgumentPooler,s=D.fourArgumentPooler,x=/\/(?!\/)/g;g.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},D.addPoolingTo(g,r),T.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},D.addPoolingTo(T,s);var j={forEach:i,map:o,mapIntoWithKeyPrefixInternal:N,count:C,toArray:c};A.exports=j},function(A,M,t){"use strict";function I(A,M){var t=y.hasOwnProperty(M)?y[M]:null;w.hasOwnProperty(M)&&(t!==x.OVERRIDE_BASE?B(!1):void 0),A.hasOwnProperty(M)&&(t!==x.DEFINE_MANY&&t!==x.DEFINE_MANY_MERGED?B(!1):void 0)}function g(A,M){if(M){"function"==typeof M?B(!1):void 0,C.isValidElement(M)?B(!1):void 0;var t=A.prototype;M.hasOwnProperty(s)&&u.mixins(A,M.mixins);for(var g in M)if(M.hasOwnProperty(g)&&g!==s){var e=M[g];if(I(t,g),u.hasOwnProperty(g))u[g](A,e);else{var i=y.hasOwnProperty(g),N=t.hasOwnProperty(g),o="function"==typeof e,n=o&&!i&&!N&&M.autobind!==!1;if(n)t.__reactAutoBindMap||(t.__reactAutoBindMap={}),t.__reactAutoBindMap[g]=e,t[g]=e;else if(N){var c=y[g];!i||c!==x.DEFINE_MANY_MERGED&&c!==x.DEFINE_MANY?B(!1):void 0,c===x.DEFINE_MANY_MERGED?t[g]=T(t[g],e):c===x.DEFINE_MANY&&(t[g]=E(t[g],e))}else t[g]=e}}}}function e(A,M){if(M)for(var t in M){var I=M[t];if(M.hasOwnProperty(t)){var g=t in u;g?B(!1):void 0;var e=t in A;e?B(!1):void 0,A[t]=I}}}function i(A,M){A&&M&&"object"==typeof A&&"object"==typeof M?void 0:B(!1);for(var t in M)M.hasOwnProperty(t)&&(void 0!==A[t]?B(!1):void 0,A[t]=M[t]);return A}function T(A,M){return function(){var t=A.apply(this,arguments),I=M.apply(this,arguments);if(null==t)return I;if(null==I)return t;var g={};return i(g,t),i(g,I),g}}function E(A,M){return function(){A.apply(this,arguments),M.apply(this,arguments)}}function N(A,M){var t=M.bind(A);return t}function o(A){for(var M in A.__reactAutoBindMap)if(A.__reactAutoBindMap.hasOwnProperty(M)){var t=A.__reactAutoBindMap[M];A[M]=N(A,t)}}var n=t(207),C=t(13),c=(t(71),t(70),t(222)),D=t(4),a=t(50),B=t(2),Q=t(59),r=t(27),s=(t(3),r({mixins:null})),x=Q({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),j=[],y={mixins:x.DEFINE_MANY,statics:x.DEFINE_MANY,propTypes:x.DEFINE_MANY,contextTypes:x.DEFINE_MANY,childContextTypes:x.DEFINE_MANY,getDefaultProps:x.DEFINE_MANY_MERGED,getInitialState:x.DEFINE_MANY_MERGED,getChildContext:x.DEFINE_MANY_MERGED,render:x.DEFINE_ONCE,componentWillMount:x.DEFINE_MANY,componentDidMount:x.DEFINE_MANY,componentWillReceiveProps:x.DEFINE_MANY,shouldComponentUpdate:x.DEFINE_ONCE,componentWillUpdate:x.DEFINE_MANY,componentDidUpdate:x.DEFINE_MANY,componentWillUnmount:x.DEFINE_MANY,updateComponent:x.OVERRIDE_BASE},u={displayName:function(A,M){A.displayName=M},mixins:function(A,M){if(M)for(var t=0;t"+T+""},receiveComponent:function(A,M){if(A!==this._currentElement){this._currentElement=A;var t=""+A;if(t!==this._stringText){this._stringText=t;var g=i.getNode(this._rootNodeID);I.updateTextContent(g,t)}}},unmountComponent:function(){e.unmountIDFromEnvironment(this._rootNodeID)}}),A.exports=o},function(A,M,t){"use strict";function I(){this.reinitializeTransaction()}var g=t(18),e=t(73),i=t(4),T=t(20),E={initialize:T,close:function(){C.isBatchingUpdates=!1}},N={initialize:T,close:g.flushBatchedUpdates.bind(g)},o=[N,E];i(I.prototype,e.Mixin,{getTransactionWrappers:function(){return o}});var n=new I,C={isBatchingUpdates:!1,batchedUpdates:function(A,M,t,I,g,e){var i=C.isBatchingUpdates;C.isBatchingUpdates=!0,i?A(M,t,I,g,e):n.perform(A,null,M,t,I,g,e)}};A.exports=C},function(A,M,t){"use strict";function I(){if(!L){L=!0,Q.EventEmitter.injectReactEventListener(B),Q.EventPluginHub.injectEventPluginOrder(T),Q.EventPluginHub.injectInstanceHandle(r),Q.EventPluginHub.injectMount(s),Q.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:u,EnterLeaveEventPlugin:E,ChangeEventPlugin:e,SelectEventPlugin:j,BeforeInputEventPlugin:g}),Q.NativeComponent.injectGenericComponentClass(D),Q.NativeComponent.injectTextComponentClass(a),Q.Class.injectMixin(n),Q.DOMProperty.injectDOMPropertyConfig(o),Q.DOMProperty.injectDOMPropertyConfig(w),Q.EmptyComponent.injectEmptyComponent("noscript"),Q.Updates.injectReconcileTransaction(x),Q.Updates.injectBatchingStrategy(c),Q.RootIndex.injectCreateReactRootIndex(N.canUseDOM?i.createReactRootIndex:y.createReactRootIndex),Q.Component.injectEnvironment(C)}}var g=t(429),e=t(431),i=t(432),T=t(434),E=t(435),N=t(10),o=t(438),n=t(440),C=t(109),c=t(212),D=t(444),a=t(211),B=t(452),Q=t(453),r=t(48),s=t(12),x=t(457),j=t(463),y=t(464),u=t(465),w=t(462),L=!1;A.exports={inject:I}},function(A,M,t){"use strict";function I(){if(n.current){var A=n.current.getName();if(A)return" Check the render method of ` + "`" + `"+A+"` + "`" + `."}return""}function g(A,M){if(A._store&&!A._store.validated&&null==A.key){A._store.validated=!0;e("uniqueKey",A,M)}}function e(A,M,t){var g=I();if(!g){var e="string"==typeof t?t:t.displayName||t.name;e&&(g=" Check the top-level render call using <"+e+">.")}var i=D[A]||(D[A]={});if(i[g])return null;i[g]=!0;var T={parentOrOwner:g,url:" See https://fb.me/react-warning-keys for more information.",childOwner:null};return M&&M._owner&&M._owner!==n.current&&(T.childOwner=" It was passed a child from "+M._owner.getName()+"."),T}function i(A,M){if("object"==typeof A)if(Array.isArray(A))for(var t=0;t/,e={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(A){var M=I(A);return A.replace(g," "+e.CHECKSUM_ATTR_NAME+'="'+M+'"$&')},canReuseMarkup:function(A,M){var t=M.getAttribute(e.CHECKSUM_ATTR_NAME);t=t&&parseInt(t,10);var g=I(A);return g===t}};A.exports=e},function(A,M,t){"use strict";var I=t(59),g=I({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOVE_NODE:null,SET_MARKUP:null,TEXT_CONTENT:null});A.exports=g},function(A,M,t){"use strict";function I(A){if("function"==typeof A.type)return A.type;var M=A.type,t=n[M];return null==t&&(n[M]=t=N(M)),t}function g(A){return o?void 0:E(!1),new o(A.type,A.props)}function e(A){return new C(A)}function i(A){return A instanceof C}var T=t(4),E=t(2),N=null,o=null,n={},C=null,c={injectGenericComponentClass:function(A){o=A},injectTextComponentClass:function(A){C=A},injectComponentClasses:function(A){T(n,A)}},D={getComponentClassForElement:I,createInternalComponent:g,createInstanceForText:e,isTextComponent:i,injection:c};A.exports=D},function(A,M,t){"use strict";function I(A,M){}var g=(t(3),{isMounted:function(A){return!1},enqueueCallback:function(A,M){},enqueueForceUpdate:function(A){I(A,"forceUpdate")},enqueueReplaceState:function(A,M){I(A,"replaceState")},enqueueSetState:function(A,M){I(A,"setState")},enqueueSetProps:function(A,M){I(A,"setProps")},enqueueReplaceProps:function(A,M){I(A,"replaceProps")}});A.exports=g},function(A,M,t){"use strict";function I(A){function M(M,t,I,g,e,i){if(g=g||y,i=i||I,null==t[I]){var T=s[e];return M?new Error("Required "+T+" ` + "`" + `"+i+"` + "`" + ` was not specified in "+("` + "`" + `"+g+"` + "`" + `.")):null}return A(t,I,g,e,i)}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}function g(A){function M(M,t,I,g,e){var i=M[t],T=a(i);if(T!==A){var E=s[g],N=B(i);return new Error("Invalid "+E+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+N+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected ")+("` + "`" + `"+A+"` + "`" + `."))}return null}return I(M)}function e(){return I(x.thatReturns(null))}function i(A){function M(M,t,I,g,e){var i=M[t];if(!Array.isArray(i)){var T=s[g],E=a(i);return new Error("Invalid "+T+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+E+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected an array."))}for(var N=0;N>"}var r=t(13),s=t(70),x=t(20),j=t(118),y="<>",u={array:g("array"),bool:g("boolean"),func:g("function"),number:g("number"),object:g("object"),string:g("string"),any:e(),arrayOf:i,element:T(),instanceOf:E,node:C(),objectOf:o,oneOf:N,oneOfType:n,shape:c};A.exports=u},function(A,M){"use strict";var t={injectCreateReactRootIndex:function(A){I.createReactRootIndex=A}},I={createReactRootIndex:null,injection:t};A.exports=I},function(A,M){"use strict";var t={currentScrollLeft:0,currentScrollTop:0,refreshScrollValues:function(A){t.currentScrollLeft=A.x,t.currentScrollTop=A.y}};A.exports=t},function(A,M,t){"use strict";function I(A,M){if(null==M?g(!1):void 0,null==A)return M;var t=Array.isArray(A),I=Array.isArray(M);return t&&I?(A.push.apply(A,M),A):t?(A.push(M),A):I?[A].concat(M):[A,M]}var g=t(2);A.exports=I},function(A,M){"use strict";var t=function(A,M,t){Array.isArray(A)?A.forEach(M,t):A&&M.call(t,A)};A.exports=t},function(A,M,t){"use strict";function I(){return!e&&g.canUseDOM&&(e="textContent"in document.documentElement?"textContent":"innerText"),e}var g=t(10),e=null;A.exports=I},function(A,M){"use strict";function t(A){var M=A&&A.nodeName&&A.nodeName.toLowerCase();return M&&("input"===M&&I[A.type]||"textarea"===M)}var I={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};A.exports=t},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(){for(var A=arguments.length,M=Array(A),t=0;t=0&&s.splice(M,1)}function T(A){var M=document.createElement("style");return M.type="text/css",e(A,M),M}function E(A){var M=document.createElement("link");return M.rel="stylesheet",e(A,M),M}function N(A,M){var t,I,g;if(M.singleton){var e=r++;t=Q||(Q=T(M)),I=o.bind(null,t,e,!1),g=o.bind(null,t,e,!0)}else A.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(t=E(M),I=C.bind(null,t),g=function(){i(t),t.href&&URL.revokeObjectURL(t.href)}):(t=T(M),I=n.bind(null,t),g=function(){i(t)});return I(A),function(M){if(M){if(M.css===A.css&&M.media===A.media&&M.sourceMap===A.sourceMap)return;I(A=M)}else g()}}function o(A,M,t,I){var g=t?"":I.css;if(A.styleSheet)A.styleSheet.cssText=x(M,g);else{var e=document.createTextNode(g),i=A.childNodes;i[M]&&A.removeChild(i[M]),i.length?A.insertBefore(e,i[M]):A.appendChild(e)}}function n(A,M){var t=M.css,I=M.media;if(I&&A.setAttribute("media",I),A.styleSheet)A.styleSheet.cssText=t;else{for(;A.firstChild;)A.removeChild(A.firstChild);A.appendChild(document.createTextNode(t))}}function C(A,M){var t=M.css,I=M.sourceMap;I&&(t+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(I))))+" */");var g=new Blob([t],{type:"text/css"}),e=A.href;A.href=URL.createObjectURL(g),e&&URL.revokeObjectURL(e)}var c={},D=function(A){var M;return function(){return"undefined"==typeof M&&(M=A.apply(this,arguments)),M}},a=D(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),B=D(function(){return document.head||document.getElementsByTagName("head")[0]}),Q=null,r=0,s=[];A.exports=function(A,M){M=M||{},"undefined"==typeof M.singleton&&(M.singleton=a()),"undefined"==typeof M.insertAt&&(M.insertAt="bottom");var t=g(A);return I(t,M),function(A){for(var e=[],i=0;i",'"',"` + "`" + `"," ","\r","\n","\t"],D=["{","}","|","\\","^","` + "`" + `"].concat(c),a=["'"].concat(D),B=["%","/","?",";","#"].concat(a),Q=["/","?","#"],r=255,s=/^[+a-z0-9A-Z_-]{0,63}$/,x=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,j={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},u={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=t(360);I.prototype.parse=function(A,M,t){if(!N.isString(A))throw new TypeError("Parameter 'url' must be a string, not "+typeof A);var I=A.indexOf("?"),g=I!==-1&&I127?"x":O[F];if(!m.match(s)){var k=U.slice(0,Y),R=U.slice(Y+1),J=O.match(x);J&&(k.push(J[1]),R.unshift(J[2])),R.length&&(T="/"+R.join(".")+T),this.hostname=k.join(".");break}}}this.hostname.length>r?this.hostname="":this.hostname=this.hostname.toLowerCase(),z||(this.hostname=E.toASCII(this.hostname));var G=this.port?":"+this.port:"",H=this.hostname||"";this.host=H+G,this.href+=this.host,z&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==T[0]&&(T="/"+T))}if(!j[D])for(var Y=0,p=a.length;Y0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return t.search=A.search,t.query=A.query,N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!j.length)return t.pathname=null,t.search?t.path="/"+t.search:t.path=null,t.href=t.format(),t;for(var l=j.slice(-1)[0],Y=(t.host||A.host||j.length>1)&&("."===l||".."===l)||""===l,d=0,h=j.length;h>=0;h--)l=j[h],"."===l?j.splice(h,1):".."===l?(j.splice(h,1),d++):d&&(j.splice(h,1),d--);if(!s&&!x)for(;d--;d)j.unshift("..");!s||""===j[0]||j[0]&&"/"===j[0].charAt(0)||j.unshift(""),Y&&"/"!==j.join("/").substr(-1)&&j.push("");var S=""===j[0]||j[0]&&"/"===j[0].charAt(0);if(w){t.hostname=t.host=S?"":j.length?j.shift():"";var L=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return s=s||t.host&&j.length,s&&!S&&j.unshift(""),j.length?t.pathname=j.join("/"):(t.pathname=null,t.path=null),N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=A.auth||t.auth,t.slashes=t.slashes||A.slashes,t.href=t.format(),t},I.prototype.parseHost=function(){var A=this.host,M=n.exec(A);M&&(M=M[0],":"!==M&&(this.port=M.substr(1)),A=A.substr(0,A.length-M.length)),A&&(this.hostname=A)}},function(A,M){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};A.exports=function(A,M){return"number"!=typeof M||t[A]?M:M+"px"}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M,t){return P.LoggedIn()?t():(location.pathname!==z.minioBrowserPrefix&&location.pathname!==z.minioBrowserPrefix+"/"||M(z.minioBrowserPrefix+"/login"),t())}function i(A,M){P.LoggedIn()&&M(""+z.minioBrowserPrefix)}function T(){q<2&&setTimeout(function(){document.querySelector(".page-load").classList.add("pl-"+q),q++,T()},K[q])}t(498);var E=t(1),N=g(E),o=t(16),n=g(o),C=t(484),c=g(C),D=t(125),a=g(D),B=t(230),Q=g(B),r=t(190),s=g(r),x=t(191),j=g(x),y=t(65),u=g(y),w=t(187),L=g(w),l=t(393),Y=g(l),d=t(22),h=g(d),S=t(42),z=(g(S),t(26)),U=t(19),p=I(U),O=t(255),m=g(O),F=t(245),f=g(F),k=t(241),R=g(k),J=t(497),G=(g(J),t(131)),H=g(G),b=t(60),X=g(b);window.Web=H.default;var v=(0,Q.default)(c.default)(a.default)(m.default),W=(0,h.default)(function(A){return A})(R.default),V=(0,h.default)(function(A){return A})(f.default),P=new H.default(window.location.protocol+"//"+window.location.host+z.minioBrowserPrefix+"/webrpc",v.dispatch);window.web=P,v.dispatch(p.setWeb(P));var Z=function(A){return N.default.createElement("div",null,A.children)};n.default.render(N.default.createElement(Y.default,{store:v,web:P},N.default.createElement(j.default,{history:u.default},N.default.createElement(s.default,{path:"/",component:Z},N.default.createElement(s.default,{path:"minio",component:Z},N.default.createElement(L.default,{component:W,onEnter:e}),N.default.createElement(s.default,{path:"login",component:V,onEnter:i}),N.default.createElement(s.default,{path:":bucket",component:W,onEnter:e}),N.default.createElement(s.default,{path:":bucket/*",component:W,onEnter:e}))))),document.getElementById("root"));var K=[0,400],q=0;T(),X.default.getItem("newlyUpdated")&&(v.dispatch(p.showAlert({type:"success",message:"Updated to the latest UI Version."})),X.default.removeItem("newlyUpdated"))},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t-1})))}},{key:"selectPrefix",value:function(A,M){A.preventDefault();var t=this.props,I=(t.dispatch,t.currentPath),g=(t.web,t.currentBucket),e=encodeURI(M);if(M.endsWith("/")||""===M){if(M===I)return;D.default.push(TA.pathJoin(g,e))}else window.location=window.location.origin+"/minio/download/"+g+"/"+e+"?token="+DA.default.getItem("token")}},{key:"makeBucket",value:function(A){A.preventDefault();var M=this.refs.makeBucketRef.value;this.refs.makeBucketRef.value="";var t=this.props,I=t.web,g=t.dispatch;this.hideMakeBucketModal(),I.MakeBucket({bucketName:M}).then(function(){g(eA.addBucket(M)),g(eA.selectBucket(M))}).catch(function(A){return g(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideMakeBucketModal",value:function(){var A=this.props.dispatch;A(eA.hideMakeBucketModal())}},{key:"showMakeBucketModal",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showMakeBucketModal())}},{key:"showAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showAbout())}},{key:"hideAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAbout())}},{key:"showBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showBucketPolicy())}},{key:"hideBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideBucketPolicy())}},{key:"uploadFile",value:function(A){A.preventDefault();var M=this.props,t=M.dispatch,I=M.buckets;if(0===I.length)return void t(eA.showAlert({type:"danger",message:"Bucket needs to be created before trying to upload files."}));var g=A.target.files[0];A.target.value=null,this.xhr=new XMLHttpRequest,t(eA.uploadFile(g,this.xhr))}},{key:"removeObject",value:function(){var A=this,M=this.props,t=M.web,I=M.dispatch,g=M.currentPath,e=M.currentBucket,i=M.deleteConfirmation;t.RemoveObject({bucketName:e,objectName:i.object}).then(function(){A.hideDeleteConfirmation(),I(eA.selectPrefix(g))}).catch(function(A){return I(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideAlert",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAlert())}},{key:"showDeleteConfirmation",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.showDeleteConfirmation(M))}},{key:"hideDeleteConfirmation",value:function(){var A=this.props.dispatch;A(eA.hideDeleteConfirmation())}},{key:"shareObject",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.shareObject(M))}},{key:"hideShareObjectModal",value:function(){var A=this.props.dispatch;A(eA.hideShareObject())}},{key:"dataType",value:function(A,M){return NA.getDataType(A,M)}},{key:"sortObjectsByName",value:function(A){var M=this.props,t=M.dispatch,I=M.objects,g=M.sortNameOrder;t(eA.setObjects(TA.sortObjectsByName(I,!g))),t(eA.setSortNameOrder(!g))}},{key:"sortObjectsBySize",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortSizeOrder;M(eA.setObjects(TA.sortObjectsBySize(t,!I))),M(eA.setSortSizeOrder(!I))}},{key:"sortObjectsByDate",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortDateOrder;M(eA.setObjects(TA.sortObjectsByDate(t,!I))),M(eA.setSortDateOrder(!I))}},{key:"logout",value:function(A){var M=this.props.web;A.preventDefault(),M.Logout(),D.default.push(oA.minioBrowserPrefix+"/login")}},{key:"landingPage",value:function(A){A.preventDefault(),this.props.dispatch(eA.selectBucket(this.props.buckets[0]))}},{key:"fullScreen",value:function(A){A.preventDefault();var M=document.documentElement;M.requestFullscreen&&M.requestFullscreen(),M.mozRequestFullScreen&&M.mozRequestFullScreen(),M.webkitRequestFullscreen&&M.webkitRequestFullscreen(),M.msRequestFullscreen&&M.msRequestFullscreen()}},{key:"toggleSidebar",value:function(A){this.props.dispatch(eA.setSidebarStatus(A))}},{key:"hideSidebar",value:function(A){var M=A||window.event,t=M.srcElement||M.target;3===t.nodeType&&(t=t.parentNode);var I=t.id;"feh-trigger"!==I&&this.props.dispatch(eA.setSidebarStatus(!1))}},{key:"showSettings",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showSettings())}},{key:"showMessage",value:function(){var A=this.props.dispatch;A(eA.showAlert({type:"success",message:"Link copied to clipboard!"})),this.hideShareObjectModal()}},{key:"selectTexts",value:function(){this.refs.copyTextInput.select()}},{key:"handleExpireValue",value:function(A,M){M===-1?this.refs[A].stepDown(1):this.refs[A].stepUp(1),7==this.refs.expireDays.value&&(this.refs.expireHours.value=0,this.refs.expireMins.value=0)}},{key:"render",value:function(){var A=this.props.storageInfo,M=A.total,t=A.free,I=this.props,g=I.showMakeBucketModal,e=I.alert,i=I.sortNameOrder,T=I.sortSizeOrder,E=I.sortDateOrder,N=I.showAbout,n=I.showBucketPolicy,c=this.props.serverInfo,D=c.version,a=c.memory,Q=c.platform,r=c.runtime,x=this.props.sidebarStatus,y=this.props.showSettings,w=this.props,l=w.policies,d=w.currentBucket,S=(w.currentPath,this.props.deleteConfirmation),U=this.props.shareObject,p=this.props,O=p.web,F=p.prefixWritable,k=y?o.default.createElement(V.default,null):o.default.createElement("noscript",null),J=o.default.createElement(L.default,{className:(0,C.default)({alert:!0,animated:!0,fadeInDown:e.show,fadeOutUp:!e.show}),bsStyle:e.type,onDismiss:this.hideAlert.bind(this)},o.default.createElement("div",{className:"text-center"},e.message));e.message||(J="");var H=(o.default.createElement(h.default,{id:"tt-sign-out"},"Sign out"),o.default.createElement(h.default,{id:"tt-upload-file"},"Upload file")),X=o.default.createElement(h.default,{id:"tt-create-bucket"},"Create bucket"),W="",P="",K="",_=M-t,AA=_/M*100+"%";O.LoggedIn()?P=o.default.createElement($.default,{fullScreen:this.fullScreen.bind(this),showAbout:this.showAbout.bind(this),showSettings:this.showSettings.bind(this),logout:this.logout.bind(this)}):W=o.default.createElement("a",{className:"btn btn-danger",href:"/minio/login"},"Login"),O.LoggedIn()&&(K=o.default.createElement("div",{className:"feh-usage"},o.default.createElement("div",{className:"fehu-chart"},o.default.createElement("div",{style:{width:AA}})),o.default.createElement("ul",null,o.default.createElement("li",null,"Used:",B.default.filesize(M-t)),o.default.createElement("li",{className:"pull-right"},"Free:",B.default.filesize(M-_)))));var tA="";return O.LoggedIn()?tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," "))),o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-bucket",onClick:this.showMakeBucketModal.bind(this)},o.default.createElement("i",{className:"fa fa-hdd-o"}))))):F&&(tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," ")))))),o.default.createElement("div",{className:(0,C.default)({"file-explorer":!0,toggled:x})},o.default.createElement(R.default,{landingPage:this.landingPage.bind(this),searchBuckets:this.searchBuckets.bind(this),selectBucket:this.selectBucket.bind(this),clickOutside:this.hideSidebar.bind(this),showPolicy:this.showBucketPolicy.bind(this)}),o.default.createElement("div",{className:"fe-body"},o.default.createElement(m.default,null,J,o.default.createElement("header",{className:"fe-header-mobile hidden-lg hidden-md"},o.default.createElement("div",{id:"feh-trigger",className:"feh-trigger "+(0,C.default)({"feht-toggled":x}),onClick:this.toggleSidebar.bind(this,!x)},o.default.createElement("div",{className:"feht-lines"},o.default.createElement("div",{className:"top"}),o.default.createElement("div",{className:"center"}),o.default.createElement("div",{className:"bottom"}))),o.default.createElement("img",{className:"mh-logo",src:IA.default,alt:""})),o.default.createElement("header",{className:"fe-header"},o.default.createElement(G.default,{selectPrefix:this.selectPrefix.bind(this)}),K,o.default.createElement("ul",{className:"feh-actions"},o.default.createElement(b.default,null),W,P)),o.default.createElement("div",{className:"feb-container"},o.default.createElement("header",{className:"fesl-row","data-type":"folder"},o.default.createElement("div",{className:"fesl-item fi-name",onClick:this.sortObjectsByName.bind(this),"data-sort":"name"},"Name",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-alpha-desc":i,"fa-sort-alpha-asc":!i})})),o.default.createElement("div",{className:"fesl-item fi-size",onClick:this.sortObjectsBySize.bind(this),"data-sort":"size"},"Size",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-amount-desc":T,"fa-sort-amount-asc":!T})})),o.default.createElement("div",{className:"fesl-item fi-modified",onClick:this.sortObjectsByDate.bind(this),"data-sort":"last-modified"},"Last Modified",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-numeric-desc":E,"fa-sort-numeric-asc":!E})})),o.default.createElement("div",{className:"fesl-item fi-actions"}))),o.default.createElement("div",{className:"feb-container"},o.default.createElement(f.default,{dataType:this.dataType.bind(this),selectPrefix:this.selectPrefix.bind(this),showDeleteConfirmation:this.showDeleteConfirmation.bind(this),shareObject:this.shareObject.bind(this)})),o.default.createElement(v.default,null),tA,o.default.createElement(s.default,{className:"modal-create-bucket",bsSize:"small",animation:!1,show:g,onHide:this.hideMakeBucketModal.bind(this)},o.default.createElement("button",{className:"close close-alt",onClick:this.hideMakeBucketModal.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement(j.default,null,o.default.createElement("form",{onSubmit:this.makeBucket.bind(this)},o.default.createElement("div",{className:"input-group"},o.default.createElement("input",{className:"ig-text",type:"text",ref:"makeBucketRef",placeholder:"Bucket Name",autoFocus:!0}),o.default.createElement("i",{className:"ig-helpers"}))))),o.default.createElement(s.default,{className:"modal-about modal-dark",animation:!1,show:N,onHide:this.hideAbout.bind(this)},o.default.createElement("button",{className:"close",onClick:this.hideAbout.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement("div",{className:"ma-inner"},o.default.createElement("div",{className:"mai-item hidden-xs"},o.default.createElement("a",{href:"https://minio.io",target:"_blank"},o.default.createElement("img",{className:"maii-logo",src:IA.default,alt:""}))),o.default.createElement("div",{className:"mai-item"},o.default.createElement("ul",{className:"maii-list"},o.default.createElement("li",null,o.default.createElement("div",null,"Version"),o.default.createElement("small",null,D)),o.default.createElement("li",null,o.default.createElement("div",null,"Memory"),o.default.createElement("small",null,a)),o.default.createElement("li",null,o.default.createElement("div",null,"Platform"),o.default.createElement("small",null,Q)),o.default.createElement("li",null,o.default.createElement("div",null,"Runtime"),o.default.createElement("small",null,r)))))),o.default.createElement(s.default,{className:"modal-policy",animation:!1,show:n,onHide:this.hideBucketPolicy.bind(this)},o.default.createElement(u.default,null,"Bucket Policy (",d,")",o.default.createElement("button",{className:"close close-alt",onClick:this.hideBucketPolicy.bind(this)},o.default.createElement("span",null,"×"))),o.default.createElement("div",{className:"pm-body"},o.default.createElement(Z.default,{bucket:d}),l.map(function(A,M){return o.default.createElement(q.default,{key:M,prefix:A.prefix,policy:A.policy})}))),o.default.createElement(MA.default,{show:S.show,icon:"fa fa-exclamation-triangle mci-red",text:"Are you sure you want to delete?",sub:"This cannot be undone!",okText:"Delete",cancelText:"Cancel",okHandler:this.removeObject.bind(this),cancelHandler:this.hideDeleteConfirmation.bind(this)}),o.default.createElement(s.default,{show:U.show,animation:!1,onHide:this.hideShareObjectModal.bind(this),bsSize:"small"},o.default.createElement(u.default,null,"Share Object"),o.default.createElement(j.default,null,o.default.createElement("div",{className:"input-group copy-text"},o.default.createElement("label",null,"Shareable Link"),o.default.createElement("input",{type:"text",ref:"copyTextInput",readOnly:"readOnly",value:window.location.protocol+"//"+U.url,onClick:this.selectTexts.bind(this)})),o.default.createElement("div",{className:"input-group",style:{display:O.LoggedIn()?"block":"none"}},o.default.createElement("label",null,"Expires in"),o.default.createElement("div",{className:"set-expire"},o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireDays",1)}),o.default.createElement("div",{className:"set-expire-title"},"Days"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireDays",type:"number",min:0,max:7,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireDays",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireHours",1)}),o.default.createElement("div",{className:"set-expire-title"},"Hours"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireHours",type:"number",min:0,max:24,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireHours",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireMins",1)}),o.default.createElement("div",{className:"set-expire-title"},"Minutes"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireMins",type:"number",min:1,max:60,defaultValue:45})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireMins",-1)}))))),o.default.createElement("div",{className:"modal-footer"},o.default.createElement(CA.default,{text:U.url,onCopy:this.showMessage.bind(this)},o.default.createElement("button",{className:"btn btn-success"},"Copy Link")),o.default.createElement("button",{className:"btn btn-link",onClick:this.hideShareObjectModal.bind(this)},"Cancel"))),k)))}}]),M}(o.default.Component);M.default=aA},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(91),N=I(E),o=function(A){var M=A.fullScreen,t=A.showAbout,I=A.showSettings,g=A.logout;return e.default.createElement("li",null,e.default.createElement(N.default,{pullRight:!0,id:"top-right-menu"},e.default.createElement(N.default.Toggle,{noCaret:!0},e.default.createElement("i",{className:"fa fa-reorder"})),e.default.createElement(N.default.Menu,{className:"dropdown-menu-right"},e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://github.com/minio/miniobrowser"},"Github ",e.default.createElement("i",{className:"fa fa-github"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:M},"Fullscreen ",e.default.createElement("i",{className:"fa fa-expand"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://docs.minio.io/"},"Documentation ",e.default.createElement("i",{className:"fa fa-book"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://slack.minio.io"},"Ask for help ",e.default.createElement("i",{className:"fa fa-question-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:t},"About ",e.default.createElement("i",{className:"fa fa-info-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:I},"Settings ",e.default.createElement("i",{className:"fa fa-cog"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:g},"Sign Out ",e.default.createElement("i",{className:"fa fa-sign-out"}))))))};M.default=(0,T.default)(function(A){return A})(o)},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(95),N=I(E),o=t(94),n=I(o),C=function(A){var M=A.latestUiVersion;return M===currentUiVersion?e.default.createElement("noscript",null):e.default.createElement("li",{className:"hidden-xs hidden-sm"},e.default.createElement("a",{href:""},e.default.createElement(n.default,{placement:"left",overlay:e.default.createElement(N.default,{id:"tt-version-update"},"New update available. Click to refresh.")}," ",e.default.createElement("i",{className:"fa fa-refresh"})," ")))};M.default=(0,T.default)(function(A){return{latestUiVersion:A.latestUiVersion}})(C)},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){ -if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{buckets:[],visibleBuckets:[],objects:[],storageInfo:{},serverInfo:{},currentBucket:"",currentPath:"",showMakeBucketModal:!1,uploads:{},alert:{show:!1,type:"danger",message:""},loginError:!1,sortNameOrder:!1,sortSizeOrder:!1,sortDateOrder:!1,latestUiVersion:currentUiVersion,sideBarActive:!1,loginRedirectPath:E.minioBrowserPrefix,settings:{accessKey:"",secretKey:"",secretKeyVisible:!1},showSettings:!1,policies:[],deleteConfirmation:{object:"",show:!1},shareObject:{show:!1,url:"",expiry:604800},prefixWritable:!1},M=arguments[1],t=Object.assign({},A);switch(M.type){case T.SET_WEB:t.web=M.web;break;case T.SET_BUCKETS:t.buckets=M.buckets;break;case T.ADD_BUCKET:t.buckets=[M.bucket].concat(e(t.buckets)),t.visibleBuckets=[M.bucket].concat(e(t.visibleBuckets));break;case T.SET_VISIBLE_BUCKETS:t.visibleBuckets=M.visibleBuckets;break;case T.SET_CURRENT_BUCKET:t.currentBucket=M.currentBucket;break;case T.SET_OBJECTS:t.objects=M.objects;break;case T.SET_CURRENT_PATH:t.currentPath=M.currentPath;break;case T.SET_STORAGE_INFO:t.storageInfo=M.storageInfo;break;case T.SET_SERVER_INFO:t.serverInfo=M.serverInfo;break;case T.SHOW_MAKEBUCKET_MODAL:t.showMakeBucketModal=M.showMakeBucketModal;break;case T.UPLOAD_PROGRESS:t.uploads=Object.assign({},t.uploads),t.uploads[M.slug].loaded=M.loaded;break;case T.ADD_UPLOAD:t.uploads=Object.assign({},t.uploads,g({},M.slug,{loaded:0,size:M.size,xhr:M.xhr,name:M.name}));break;case T.STOP_UPLOAD:t.uploads=Object.assign({},t.uploads),delete t.uploads[M.slug];break;case T.SET_ALERT:t.alert.alertTimeout&&clearTimeout(t.alert.alertTimeout),M.alert.show?t.alert=M.alert:t.alert=Object.assign({},t.alert,{show:!1});break;case T.SET_LOGIN_ERROR:t.loginError=!0;break;case T.SET_SHOW_ABORT_MODAL:t.showAbortModal=M.showAbortModal;break;case T.SHOW_ABOUT:t.showAbout=M.showAbout;break;case T.SET_SORT_NAME_ORDER:t.sortNameOrder=M.sortNameOrder;break;case T.SET_SORT_SIZE_ORDER:t.sortSizeOrder=M.sortSizeOrder;break;case T.SET_SORT_DATE_ORDER:t.sortDateOrder=M.sortDateOrder;break;case T.SET_LATEST_UI_VERSION:t.latestUiVersion=M.latestUiVersion;break;case T.SET_SIDEBAR_STATUS:t.sidebarStatus=M.sidebarStatus;break;case T.SET_LOGIN_REDIRECT_PATH:t.loginRedirectPath=M.path;case T.SET_LOAD_BUCKET:t.loadBucket=M.loadBucket;break;case T.SET_LOAD_PATH:t.loadPath=M.loadPath;break;case T.SHOW_SETTINGS:t.showSettings=M.showSettings;break;case T.SET_SETTINGS:t.settings=Object.assign({},t.settings,M.settings);break;case T.SHOW_BUCKET_POLICY:t.showBucketPolicy=M.showBucketPolicy;break;case T.SET_POLICIES:t.policies=M.policies;break;case T.DELETE_CONFIRMATION:t.deleteConfirmation=Object.assign({},M.payload);break;case T.SET_SHARE_OBJECT:t.shareObject=Object.assign({},M.shareObject);break;case T.SET_PREFIX_WRITABLE:t.prefixWritable=M.prefixWritable}return t}},function(A,M,t){A.exports={default:t(260),__esModule:!0}},function(A,M,t){t(270),A.exports=t(49).Object.assign},function(A,M,t){var I=t(80);A.exports=function(A,M){return I.create(A,M)}},function(A,M,t){t(271),A.exports=t(49).Object.keys},function(A,M,t){t(272),A.exports=t(49).Object.setPrototypeOf},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M,t){var I=t(136);A.exports=function(A){if(!I(A))throw TypeError(A+" is not an object!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(263);A.exports=Object("z").propertyIsEnumerable(0)?Object:function(A){return"String"==I(A)?A.split(""):Object(A)}},function(A,M,t){var I=t(80),g=t(137),e=t(266);A.exports=t(135)(function(){var A=Object.assign,M={},t={},I=Symbol(),g="abcdefghijklmnopqrst";return M[I]=7,g.split("").forEach(function(A){t[A]=A}),7!=A({},M)[I]||Object.keys(A({},t)).join("")!=g})?function(A,M){for(var t=g(A),i=arguments,T=i.length,E=1,N=I.getKeys,o=I.getSymbols,n=I.isEnum;T>E;)for(var C,c=e(i[E++]),D=o?N(c).concat(o(c)):N(c),a=D.length,B=0;a>B;)n.call(c,C=D[B++])&&(t[C]=c[C]);return t}:Object.assign},function(A,M,t){var I=t(79),g=t(49),e=t(135);A.exports=function(A,M){var t=(g.Object||{})[A]||Object[A],i={};i[A]=M(t),I(I.S+I.F*e(function(){t(1)}),"Object",i)}},function(A,M,t){var I=t(80).getDesc,g=t(136),e=t(262),i=function(A,M){if(e(A),!g(M)&&null!==M)throw TypeError(M+": can't set as prototype!")};A.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(A,M,g){try{g=t(134)(Function.call,I(Object.prototype,"__proto__").set,2),g(A,[]),M=!(A instanceof Array)}catch(A){M=!0}return function(A,t){return i(A,t),M?A.__proto__=t:g(A,t),A}}({},!1):void 0),check:i}},function(A,M,t){var I=t(79);I(I.S+I.F,"Object",{assign:t(267)})},function(A,M,t){var I=t(137);t(268)("keys",function(A){return function(M){return A(I(M))}})},function(A,M,t){var I=t(79);I(I.S,"Object",{setPrototypeOf:t(269).set})},function(A,M,t){function I(A){if(A)return g(A)}function g(A){ -for(var M in I.prototype)A[M]=I.prototype[M];return A}A.exports=I,I.prototype.on=I.prototype.addEventListener=function(A,M){return this._callbacks=this._callbacks||{},(this._callbacks["$"+A]=this._callbacks["$"+A]||[]).push(M),this},I.prototype.once=function(A,M){function t(){this.off(A,t),M.apply(this,arguments)}return t.fn=M,this.on(A,t),this},I.prototype.off=I.prototype.removeListener=I.prototype.removeAllListeners=I.prototype.removeEventListener=function(A,M){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+A];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+A],this;for(var I,g=0;g",'"',"` + "`" + `"," ","\r","\n","\t"],D=["{","}","|","\\","^","` + "`" + `"].concat(c),a=["'"].concat(D),B=["%","/","?",";","#"].concat(a),Q=["/","?","#"],r=255,s=/^[+a-z0-9A-Z_-]{0,63}$/,x=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,j={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},u={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=t(360);I.prototype.parse=function(A,M,t){if(!N.isString(A))throw new TypeError("Parameter 'url' must be a string, not "+typeof A);var I=A.indexOf("?"),g=I!==-1&&I127?"x":O[F];if(!m.match(s)){var k=U.slice(0,Y),R=U.slice(Y+1),J=O.match(x);J&&(k.push(J[1]),R.unshift(J[2])),R.length&&(T="/"+R.join(".")+T),this.hostname=k.join(".");break}}}this.hostname.length>r?this.hostname="":this.hostname=this.hostname.toLowerCase(),z||(this.hostname=E.toASCII(this.hostname));var G=this.port?":"+this.port:"",H=this.hostname||"";this.host=H+G,this.href+=this.host,z&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==T[0]&&(T="/"+T))}if(!j[D])for(var Y=0,p=a.length;Y0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return t.search=A.search,t.query=A.query,N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!j.length)return t.pathname=null,t.search?t.path="/"+t.search:t.path=null,t.href=t.format(),t;for(var l=j.slice(-1)[0],Y=(t.host||A.host||j.length>1)&&("."===l||".."===l)||""===l,d=0,h=j.length;h>=0;h--)l=j[h],"."===l?j.splice(h,1):".."===l?(j.splice(h,1),d++):d&&(j.splice(h,1),d--);if(!s&&!x)for(;d--;d)j.unshift("..");!s||""===j[0]||j[0]&&"/"===j[0].charAt(0)||j.unshift(""),Y&&"/"!==j.join("/").substr(-1)&&j.push("");var S=""===j[0]||j[0]&&"/"===j[0].charAt(0);if(w){t.hostname=t.host=S?"":j.length?j.shift():"";var L=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return s=s||t.host&&j.length,s&&!S&&j.unshift(""),j.length?t.pathname=j.join("/"):(t.pathname=null,t.path=null),N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=A.auth||t.auth,t.slashes=t.slashes||A.slashes,t.href=t.format(),t},I.prototype.parseHost=function(){var A=this.host,M=n.exec(A);M&&(M=M[0],":"!==M&&(this.port=M.substr(1)),A=A.substr(0,A.length-M.length)),A&&(this.hostname=A)}},function(A,M){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};A.exports=function(A,M){return"number"!=typeof M||t[A]?M:M+"px"}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M,t){return P.LoggedIn()?t():(location.pathname!==z.minioBrowserPrefix&&location.pathname!==z.minioBrowserPrefix+"/"||M(z.minioBrowserPrefix+"/login"),t())}function i(A,M){P.LoggedIn()&&M(""+z.minioBrowserPrefix)}function T(){q<2&&setTimeout(function(){document.querySelector(".page-load").classList.add("pl-"+q),q++,T()},K[q])}t(498);var E=t(1),N=g(E),o=t(16),n=g(o),C=t(484),c=g(C),D=t(125),a=g(D),B=t(230),Q=g(B),r=t(190),s=g(r),x=t(191),j=g(x),y=t(65),u=g(y),w=t(187),L=g(w),l=t(393),Y=g(l),d=t(22),h=g(d),S=t(42),z=(g(S),t(26)),U=t(19),p=I(U),O=t(255),m=g(O),F=t(245),f=g(F),k=t(241),R=g(k),J=t(497),G=(g(J),t(131)),H=g(G),b=t(60),X=g(b);window.Web=H.default;var v=(0,Q.default)(c.default)(a.default)(m.default),W=(0,h.default)(function(A){return A})(R.default),V=(0,h.default)(function(A){return A})(f.default),P=new H.default(window.location.protocol+"//"+window.location.host+z.minioBrowserPrefix+"/webrpc",v.dispatch);window.web=P,v.dispatch(p.setWeb(P));var Z=function(A){return N.default.createElement("div",null,A.children)};n.default.render(N.default.createElement(Y.default,{store:v,web:P},N.default.createElement(j.default,{history:u.default},N.default.createElement(s.default,{path:"/",component:Z},N.default.createElement(s.default,{path:"minio",component:Z},N.default.createElement(L.default,{component:W,onEnter:e}),N.default.createElement(s.default,{path:"login",component:V,onEnter:i}),N.default.createElement(s.default,{path:":bucket",component:W,onEnter:e}),N.default.createElement(s.default,{path:":bucket/*",component:W,onEnter:e}))))),document.getElementById("root"));var K=[0,400],q=0;T(),X.default.getItem("newlyUpdated")&&(v.dispatch(p.showAlert({type:"success",message:"Updated to the latest UI Version."})),X.default.removeItem("newlyUpdated"))},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t-1})))}},{key:"selectPrefix",value:function(A,M){A.preventDefault();var t=this.props,I=(t.dispatch,t.currentPath),g=(t.web,t.currentBucket),e=encodeURI(M);if(M.endsWith("/")||""===M){if(M===I)return;D.default.push(TA.pathJoin(g,e))}else window.location=window.location.origin+"/minio/download/"+g+"/"+e+"?token="+DA.default.getItem("token")}},{key:"makeBucket",value:function(A){A.preventDefault();var M=this.refs.makeBucketRef.value;this.refs.makeBucketRef.value="";var t=this.props,I=t.web,g=t.dispatch;this.hideMakeBucketModal(),I.MakeBucket({bucketName:M}).then(function(){g(eA.addBucket(M)),g(eA.selectBucket(M))}).catch(function(A){return g(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideMakeBucketModal",value:function(){var A=this.props.dispatch;A(eA.hideMakeBucketModal())}},{key:"showMakeBucketModal",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showMakeBucketModal())}},{key:"showAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showAbout())}},{key:"hideAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAbout())}},{key:"showBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showBucketPolicy())}},{key:"hideBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideBucketPolicy())}},{key:"uploadFile",value:function(A){A.preventDefault();var M=this.props,t=M.dispatch,I=M.buckets;if(0===I.length)return void t(eA.showAlert({type:"danger",message:"Bucket needs to be created before trying to upload files."}));var g=A.target.files[0];A.target.value=null,this.xhr=new XMLHttpRequest,t(eA.uploadFile(g,this.xhr))}},{key:"removeObject",value:function(){var A=this,M=this.props,t=M.web,I=M.dispatch,g=M.currentPath,e=M.currentBucket,i=M.deleteConfirmation;t.RemoveObject({bucketName:e,objectName:i.object}).then(function(){A.hideDeleteConfirmation(),I(eA.selectPrefix(g))}).catch(function(A){return I(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideAlert",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAlert())}},{key:"showDeleteConfirmation",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.showDeleteConfirmation(M))}},{key:"hideDeleteConfirmation",value:function(){var A=this.props.dispatch;A(eA.hideDeleteConfirmation())}},{key:"shareObject",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.shareObject(M))}},{key:"hideShareObjectModal",value:function(){var A=this.props.dispatch;A(eA.hideShareObject())}},{key:"dataType",value:function(A,M){return NA.getDataType(A,M)}},{key:"sortObjectsByName",value:function(A){var M=this.props,t=M.dispatch,I=M.objects,g=M.sortNameOrder;t(eA.setObjects(TA.sortObjectsByName(I,!g))),t(eA.setSortNameOrder(!g))}},{key:"sortObjectsBySize",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortSizeOrder;M(eA.setObjects(TA.sortObjectsBySize(t,!I))),M(eA.setSortSizeOrder(!I))}},{key:"sortObjectsByDate",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortDateOrder;M(eA.setObjects(TA.sortObjectsByDate(t,!I))),M(eA.setSortDateOrder(!I))}},{key:"logout",value:function(A){var M=this.props.web;A.preventDefault(),M.Logout(),D.default.push(oA.minioBrowserPrefix+"/login")}},{key:"landingPage",value:function(A){A.preventDefault(),this.props.dispatch(eA.selectBucket(this.props.buckets[0]))}},{key:"fullScreen",value:function(A){A.preventDefault();var M=document.documentElement;M.requestFullscreen&&M.requestFullscreen(),M.mozRequestFullScreen&&M.mozRequestFullScreen(),M.webkitRequestFullscreen&&M.webkitRequestFullscreen(),M.msRequestFullscreen&&M.msRequestFullscreen()}},{key:"toggleSidebar",value:function(A){this.props.dispatch(eA.setSidebarStatus(A))}},{key:"hideSidebar",value:function(A){var M=A||window.event,t=M.srcElement||M.target;3===t.nodeType&&(t=t.parentNode);var I=t.id;"feh-trigger"!==I&&this.props.dispatch(eA.setSidebarStatus(!1))}},{key:"showSettings",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showSettings())}},{key:"showMessage",value:function(){var A=this.props.dispatch;A(eA.showAlert({type:"success",message:"Link copied to clipboard!"})),this.hideShareObjectModal()}},{key:"selectTexts",value:function(){this.refs.copyTextInput.select()}},{key:"handleExpireValue",value:function(A,M){M===-1?this.refs[A].stepDown(1):this.refs[A].stepUp(1),7==this.refs.expireDays.value&&(this.refs.expireHours.value=0,this.refs.expireMins.value=0)}},{key:"render",value:function(){var A=this.props.storageInfo,M=A.total,t=A.free,I=this.props,g=I.showMakeBucketModal,e=I.alert,i=I.sortNameOrder,T=I.sortSizeOrder,E=I.sortDateOrder,N=I.showAbout,n=I.showBucketPolicy,c=this.props.serverInfo,D=c.version,a=c.memory,Q=c.platform,r=c.runtime,x=this.props.sidebarStatus,y=this.props.showSettings,w=this.props,l=w.policies,d=w.currentBucket,S=(w.currentPath,this.props.deleteConfirmation),U=this.props.shareObject,p=this.props,O=p.web,F=p.prefixWritable,k=y?o.default.createElement(V.default,null):o.default.createElement("noscript",null),J=o.default.createElement(L.default,{className:(0,C.default)({alert:!0,animated:!0,fadeInDown:e.show,fadeOutUp:!e.show}),bsStyle:e.type,onDismiss:this.hideAlert.bind(this)},o.default.createElement("div",{className:"text-center"},e.message));e.message||(J="");var H=(o.default.createElement(h.default,{id:"tt-sign-out"},"Sign out"),o.default.createElement(h.default,{id:"tt-upload-file"},"Upload file")),X=o.default.createElement(h.default,{id:"tt-create-bucket"},"Create bucket"),W="",P="",K="",_=M-t,AA=_/M*100+"%";O.LoggedIn()?P=o.default.createElement($.default,{fullScreenFunc:this.fullScreen.bind(this),aboutFunc:this.showAbout.bind(this),settingsFunc:this.showSettings.bind(this),logoutFunc:this.logout.bind(this)}):W=o.default.createElement("a",{className:"btn btn-danger",href:"/minio/login"},"Login"),O.LoggedIn()&&(K=o.default.createElement("div",{className:"feh-usage"},o.default.createElement("div",{className:"fehu-chart"},o.default.createElement("div",{style:{width:AA}})),o.default.createElement("ul",null,o.default.createElement("li",null,"Used:",B.default.filesize(M-t)),o.default.createElement("li",{className:"pull-right"},"Free:",B.default.filesize(M-_)))));var tA="";return O.LoggedIn()?tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," "))),o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-bucket",onClick:this.showMakeBucketModal.bind(this)},o.default.createElement("i",{className:"fa fa-hdd-o"}))))):F&&(tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," ")))))),o.default.createElement("div",{className:(0,C.default)({"file-explorer":!0,toggled:x})},o.default.createElement(R.default,{landingPage:this.landingPage.bind(this),searchBuckets:this.searchBuckets.bind(this),selectBucket:this.selectBucket.bind(this),clickOutside:this.hideSidebar.bind(this),showPolicy:this.showBucketPolicy.bind(this)}),o.default.createElement("div",{className:"fe-body"},o.default.createElement(m.default,null,J,o.default.createElement("header",{className:"fe-header-mobile hidden-lg hidden-md"},o.default.createElement("div",{id:"feh-trigger",className:"feh-trigger "+(0,C.default)({"feht-toggled":x}),onClick:this.toggleSidebar.bind(this,!x)},o.default.createElement("div",{className:"feht-lines"},o.default.createElement("div",{className:"top"}),o.default.createElement("div",{className:"center"}),o.default.createElement("div",{className:"bottom"}))),o.default.createElement("img",{className:"mh-logo",src:IA.default,alt:""})),o.default.createElement("header",{className:"fe-header"},o.default.createElement(G.default,{selectPrefix:this.selectPrefix.bind(this)}),K,o.default.createElement("ul",{className:"feh-actions"},o.default.createElement(b.default,null),W,P)),o.default.createElement("div",{className:"feb-container"},o.default.createElement("header",{className:"fesl-row","data-type":"folder"},o.default.createElement("div",{className:"fesl-item fi-name",onClick:this.sortObjectsByName.bind(this),"data-sort":"name"},"Name",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-alpha-desc":i,"fa-sort-alpha-asc":!i})})),o.default.createElement("div",{className:"fesl-item fi-size",onClick:this.sortObjectsBySize.bind(this),"data-sort":"size"},"Size",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-amount-desc":T,"fa-sort-amount-asc":!T})})),o.default.createElement("div",{className:"fesl-item fi-modified",onClick:this.sortObjectsByDate.bind(this),"data-sort":"last-modified"},"Last Modified",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-numeric-desc":E,"fa-sort-numeric-asc":!E})})),o.default.createElement("div",{className:"fesl-item fi-actions"}))),o.default.createElement("div",{className:"feb-container"},o.default.createElement(f.default,{dataType:this.dataType.bind(this),selectPrefix:this.selectPrefix.bind(this),showDeleteConfirmation:this.showDeleteConfirmation.bind(this),shareObject:this.shareObject.bind(this)})),o.default.createElement(v.default,null),tA,o.default.createElement(s.default,{className:"modal-create-bucket",bsSize:"small",animation:!1,show:g,onHide:this.hideMakeBucketModal.bind(this)},o.default.createElement("button",{className:"close close-alt",onClick:this.hideMakeBucketModal.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement(j.default,null,o.default.createElement("form",{onSubmit:this.makeBucket.bind(this)},o.default.createElement("div",{className:"input-group"},o.default.createElement("input",{className:"ig-text",type:"text",ref:"makeBucketRef",placeholder:"Bucket Name",autoFocus:!0}),o.default.createElement("i",{className:"ig-helpers"}))))),o.default.createElement(s.default,{className:"modal-about modal-dark",animation:!1,show:N,onHide:this.hideAbout.bind(this)},o.default.createElement("button",{className:"close",onClick:this.hideAbout.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement("div",{className:"ma-inner"},o.default.createElement("div",{className:"mai-item hidden-xs"},o.default.createElement("a",{href:"https://minio.io",target:"_blank"},o.default.createElement("img",{className:"maii-logo",src:IA.default,alt:""}))),o.default.createElement("div",{className:"mai-item"},o.default.createElement("ul",{className:"maii-list"},o.default.createElement("li",null,o.default.createElement("div",null,"Version"),o.default.createElement("small",null,D)),o.default.createElement("li",null,o.default.createElement("div",null,"Memory"),o.default.createElement("small",null,a)),o.default.createElement("li",null,o.default.createElement("div",null,"Platform"),o.default.createElement("small",null,Q)),o.default.createElement("li",null,o.default.createElement("div",null,"Runtime"),o.default.createElement("small",null,r)))))),o.default.createElement(s.default,{className:"modal-policy",animation:!1,show:n,onHide:this.hideBucketPolicy.bind(this)},o.default.createElement(u.default,null,"Bucket Policy (",d,")",o.default.createElement("button",{className:"close close-alt",onClick:this.hideBucketPolicy.bind(this)},o.default.createElement("span",null,"×"))),o.default.createElement("div",{className:"pm-body"},o.default.createElement(Z.default,{bucket:d}),l.map(function(A,M){return o.default.createElement(q.default,{key:M,prefix:A.prefix,policy:A.policy})}))),o.default.createElement(MA.default,{show:S.show,icon:"fa fa-exclamation-triangle mci-red",text:"Are you sure you want to delete?",sub:"This cannot be undone!",okText:"Delete",cancelText:"Cancel",okHandler:this.removeObject.bind(this),cancelHandler:this.hideDeleteConfirmation.bind(this)}),o.default.createElement(s.default,{show:U.show,animation:!1,onHide:this.hideShareObjectModal.bind(this),bsSize:"small"},o.default.createElement(u.default,null,"Share Object"),o.default.createElement(j.default,null,o.default.createElement("div",{className:"input-group copy-text"},o.default.createElement("label",null,"Shareable Link"),o.default.createElement("input",{type:"text",ref:"copyTextInput",readOnly:"readOnly",value:window.location.protocol+"//"+U.url,onClick:this.selectTexts.bind(this)})),o.default.createElement("div",{className:"input-group",style:{display:O.LoggedIn()?"block":"none"}},o.default.createElement("label",null,"Expires in"),o.default.createElement("div",{className:"set-expire"},o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireDays",1)}),o.default.createElement("div",{className:"set-expire-title"},"Days"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireDays",type:"number",min:0,max:7,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireDays",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireHours",1)}),o.default.createElement("div",{className:"set-expire-title"},"Hours"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireHours",type:"number",min:0,max:24,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireHours",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireMins",1)}),o.default.createElement("div",{className:"set-expire-title"},"Minutes"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireMins",type:"number",min:1,max:60,defaultValue:45})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireMins",-1)}))))),o.default.createElement("div",{className:"modal-footer"},o.default.createElement(CA.default,{text:U.url,onCopy:this.showMessage.bind(this)},o.default.createElement("button",{className:"btn btn-success"},"Copy Link")),o.default.createElement("button",{className:"btn btn-link",onClick:this.hideShareObjectModal.bind(this)},"Cancel"))),k)))}}]),M}(o.default.Component);M.default=aA},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(91),N=I(E),o=function(A){var M=A.fullScreenFunc,t=A.aboutFunc,I=A.settingsFunc,g=A.logoutFunc;return e.default.createElement("li",null,e.default.createElement(N.default,{pullRight:!0,id:"top-right-menu"},e.default.createElement(N.default.Toggle,{noCaret:!0},e.default.createElement("i",{className:"fa fa-reorder"})),e.default.createElement(N.default.Menu,{className:"dropdown-menu-right"},e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://github.com/minio/miniobrowser"},"Github ",e.default.createElement("i",{className:"fa fa-github"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:M},"Fullscreen ",e.default.createElement("i",{className:"fa fa-expand"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://docs.minio.io/"},"Documentation ",e.default.createElement("i",{className:"fa fa-book"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://slack.minio.io"},"Ask for help ",e.default.createElement("i",{className:"fa fa-question-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:t},"About ",e.default.createElement("i",{className:"fa fa-info-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:I},"Settings ",e.default.createElement("i",{className:"fa fa-cog"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:g},"Sign Out ",e.default.createElement("i",{className:"fa fa-sign-out"}))))))};M.default=(0,T.default)(function(A){return A})(o)},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(95),N=I(E),o=t(94),n=I(o),C=function(A){var M=A.latestUiVersion;return M===currentUiVersion?e.default.createElement("noscript",null):e.default.createElement("li",{className:"hidden-xs hidden-sm"},e.default.createElement("a",{href:""},e.default.createElement(n.default,{placement:"left",overlay:e.default.createElement(N.default,{id:"tt-version-update"},"New update available. Click to refresh.")}," ",e.default.createElement("i",{className:"fa fa-refresh"})," ")))};M.default=(0,T.default)(function(A){return{latestUiVersion:A.latestUiVersion}})(C)},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function"); +}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{buckets:[],visibleBuckets:[],objects:[],storageInfo:{},serverInfo:{},currentBucket:"",currentPath:"",showMakeBucketModal:!1,uploads:{},alert:{show:!1,type:"danger",message:""},loginError:!1,sortNameOrder:!1,sortSizeOrder:!1,sortDateOrder:!1,latestUiVersion:currentUiVersion,sideBarActive:!1,loginRedirectPath:E.minioBrowserPrefix,settings:{accessKey:"",secretKey:"",secretKeyVisible:!1},showSettings:!1,policies:[],deleteConfirmation:{object:"",show:!1},shareObject:{show:!1,url:"",expiry:604800},prefixWritable:!1},M=arguments[1],t=Object.assign({},A);switch(M.type){case T.SET_WEB:t.web=M.web;break;case T.SET_BUCKETS:t.buckets=M.buckets;break;case T.ADD_BUCKET:t.buckets=[M.bucket].concat(e(t.buckets)),t.visibleBuckets=[M.bucket].concat(e(t.visibleBuckets));break;case T.SET_VISIBLE_BUCKETS:t.visibleBuckets=M.visibleBuckets;break;case T.SET_CURRENT_BUCKET:t.currentBucket=M.currentBucket;break;case T.SET_OBJECTS:t.objects=M.objects;break;case T.SET_CURRENT_PATH:t.currentPath=M.currentPath;break;case T.SET_STORAGE_INFO:t.storageInfo=M.storageInfo;break;case T.SET_SERVER_INFO:t.serverInfo=M.serverInfo;break;case T.SHOW_MAKEBUCKET_MODAL:t.showMakeBucketModal=M.showMakeBucketModal;break;case T.UPLOAD_PROGRESS:t.uploads=Object.assign({},t.uploads),t.uploads[M.slug].loaded=M.loaded;break;case T.ADD_UPLOAD:t.uploads=Object.assign({},t.uploads,g({},M.slug,{loaded:0,size:M.size,xhr:M.xhr,name:M.name}));break;case T.STOP_UPLOAD:t.uploads=Object.assign({},t.uploads),delete t.uploads[M.slug];break;case T.SET_ALERT:t.alert.alertTimeout&&clearTimeout(t.alert.alertTimeout),M.alert.show?t.alert=M.alert:t.alert=Object.assign({},t.alert,{show:!1});break;case T.SET_LOGIN_ERROR:t.loginError=!0;break;case T.SET_SHOW_ABORT_MODAL:t.showAbortModal=M.showAbortModal;break;case T.SHOW_ABOUT:t.showAbout=M.showAbout;break;case T.SET_SORT_NAME_ORDER:t.sortNameOrder=M.sortNameOrder;break;case T.SET_SORT_SIZE_ORDER:t.sortSizeOrder=M.sortSizeOrder;break;case T.SET_SORT_DATE_ORDER:t.sortDateOrder=M.sortDateOrder;break;case T.SET_LATEST_UI_VERSION:t.latestUiVersion=M.latestUiVersion;break;case T.SET_SIDEBAR_STATUS:t.sidebarStatus=M.sidebarStatus;break;case T.SET_LOGIN_REDIRECT_PATH:t.loginRedirectPath=M.path;case T.SET_LOAD_BUCKET:t.loadBucket=M.loadBucket;break;case T.SET_LOAD_PATH:t.loadPath=M.loadPath;break;case T.SHOW_SETTINGS:t.showSettings=M.showSettings;break;case T.SET_SETTINGS:t.settings=Object.assign({},t.settings,M.settings);break;case T.SHOW_BUCKET_POLICY:t.showBucketPolicy=M.showBucketPolicy;break;case T.SET_POLICIES:t.policies=M.policies;break;case T.DELETE_CONFIRMATION:t.deleteConfirmation=Object.assign({},M.payload);break;case T.SET_SHARE_OBJECT:t.shareObject=Object.assign({},M.shareObject);break;case T.SET_PREFIX_WRITABLE:t.prefixWritable=M.prefixWritable}return t}},function(A,M,t){A.exports={default:t(260),__esModule:!0}},function(A,M,t){t(270),A.exports=t(49).Object.assign},function(A,M,t){var I=t(80);A.exports=function(A,M){return I.create(A,M)}},function(A,M,t){t(271),A.exports=t(49).Object.keys},function(A,M,t){t(272),A.exports=t(49).Object.setPrototypeOf},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M,t){var I=t(136);A.exports=function(A){if(!I(A))throw TypeError(A+" is not an object!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(263);A.exports=Object("z").propertyIsEnumerable(0)?Object:function(A){return"String"==I(A)?A.split(""):Object(A)}},function(A,M,t){var I=t(80),g=t(137),e=t(266);A.exports=t(135)(function(){var A=Object.assign,M={},t={},I=Symbol(),g="abcdefghijklmnopqrst";return M[I]=7,g.split("").forEach(function(A){t[A]=A}),7!=A({},M)[I]||Object.keys(A({},t)).join("")!=g})?function(A,M){for(var t=g(A),i=arguments,T=i.length,E=1,N=I.getKeys,o=I.getSymbols,n=I.isEnum;T>E;)for(var C,c=e(i[E++]),D=o?N(c).concat(o(c)):N(c),a=D.length,B=0;a>B;)n.call(c,C=D[B++])&&(t[C]=c[C]);return t}:Object.assign},function(A,M,t){var I=t(79),g=t(49),e=t(135);A.exports=function(A,M){var t=(g.Object||{})[A]||Object[A],i={};i[A]=M(t),I(I.S+I.F*e(function(){t(1)}),"Object",i)}},function(A,M,t){var I=t(80).getDesc,g=t(136),e=t(262),i=function(A,M){if(e(A),!g(M)&&null!==M)throw TypeError(M+": can't set as prototype!")};A.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(A,M,g){try{g=t(134)(Function.call,I(Object.prototype,"__proto__").set,2),g(A,[]),M=!(A instanceof Array)}catch(A){M=!0}return function(A,t){return i(A,t),M?A.__proto__=t:g(A,t),A}}({},!1):void 0),check:i}},function(A,M,t){var I=t(79);I(I.S+I.F,"Object",{assign:t(267)})},function(A,M,t){var I=t(137);t(268)("keys",function(A){return function(M){return A(I(M))}})},function(A,M,t){var I=t(79);I(I.S,"Object",{setPrototypeOf:t(269).set})},function(A,M,t){function I(A){if(A)return g(A); +}function g(A){for(var M in I.prototype)A[M]=I.prototype[M];return A}A.exports=I,I.prototype.on=I.prototype.addEventListener=function(A,M){return this._callbacks=this._callbacks||{},(this._callbacks["$"+A]=this._callbacks["$"+A]||[]).push(M),this},I.prototype.once=function(A,M){function t(){this.off(A,t),M.apply(this,arguments)}return t.fn=M,this.on(A,t),this},I.prototype.off=I.prototype.removeListener=I.prototype.removeAllListeners=I.prototype.removeEventListener=function(A,M){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+A];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+A],this;for(var I,g=0;g1&&(I=t[0]+"@",A=t[1]),A=A.replace(z,".");var g=A.split("."),e=T(g,M).join(".");return I+e}function N(A){for(var M,t,I=[],g=0,e=A.length;g=55296&&M<=56319&&g65535&&(A-=65536,M+=m(A>>>10&1023|55296),A=56320|1023&A),M+=m(A)}).join("")}function n(A){return A-48<10?A-22:A-65<26?A-65:A-97<26?A-97:j}function C(A,M){return A+22+75*(A<26)-((0!=M)<<5)}function c(A,M,t){var I=0;for(A=t?O(A/L):A>>1,A+=O(A/M);A>p*u>>1;I+=j)A=O(A/p);return O(I+(p+1)*A/(A+w))}function D(A){var M,t,I,g,e,T,E,N,C,D,a=[],B=A.length,Q=0,r=Y,s=l;for(t=A.lastIndexOf(d),t<0&&(t=0),I=0;I=128&&i("not-basic"),a.push(A.charCodeAt(I));for(g=t>0?t+1:0;g=B&&i("invalid-input"),N=n(A.charCodeAt(g++)),(N>=j||N>O((x-Q)/T))&&i("overflow"),Q+=N*T,C=E<=s?y:E>=s+u?u:E-s,!(NO(x/D)&&i("overflow"),T*=D;M=a.length+1,s=c(Q-e,M,0==e),O(Q/M)>x-r&&i("overflow"),r+=O(Q/M),Q%=M,a.splice(Q++,0,r)}return o(a)}function a(A){var M,t,I,g,e,T,E,o,n,D,a,B,Q,r,s,w=[];for(A=N(A),B=A.length,M=Y,t=0,e=l,T=0;T=M&&aO((x-t)/Q)&&i("overflow"),t+=(E-M)*Q,M=E,T=0;Tx&&i("overflow"),a==M){for(o=t,n=j;D=n<=e?y:n>=e+u?u:n-e,!(o= 0x80 (not a basic code point)","invalid-input":"Invalid input"},p=j-y,O=Math.floor,m=String.fromCharCode;s={version:"1.3.2",ucs2:{decode:N,encode:o},decode:D,encode:a,toASCII:Q,toUnicode:B},I=function(){return s}.call(M,t,M,A),!(void 0!==I&&(A.exports=I))}(this)}).call(M,t(128)(A),function(){return this}())},function(A,M){"use strict";A.exports={isString:function(A){return"string"==typeof A},isObject:function(A){return"object"==typeof A&&null!==A},isNull:function(A){return null===A},isNullOrUndefined:function(A){return null==A}}}]);`) -func productionIndex_bundle20170125t031051zJsBytes() ([]byte, error) { - return _productionIndex_bundle20170125t031051zJs, nil +func productionIndex_bundle20170131t003809zJsBytes() ([]byte, error) { + return _productionIndex_bundle20170131t003809zJs, nil } -func productionIndex_bundle20170125t031051zJs() (*asset, error) { - bytes, err := productionIndex_bundle20170125t031051zJsBytes() +func productionIndex_bundle20170131t003809zJs() (*asset, error) { + bytes, err := productionIndex_bundle20170131t003809zJsBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "production/index_bundle-2017-01-25T03-10-51Z.js", size: 2272141, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/index_bundle-2017-01-31T00-38-09Z.js", size: 2272159, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -370,7 +370,7 @@ func productionLoaderCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -444,7 +444,7 @@ func productionLogoSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -461,7 +461,7 @@ func productionSafariPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1485313867, 0)} + info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -522,7 +522,7 @@ var _bindata = map[string]func() (*asset, error){ "production/favicon.ico": productionFaviconIco, "production/firefox.png": productionFirefoxPng, "production/index.html": productionIndexHTML, - "production/index_bundle-2017-01-25T03-10-51Z.js": productionIndex_bundle20170125t031051zJs, + "production/index_bundle-2017-01-31T00-38-09Z.js": productionIndex_bundle20170131t003809zJs, "production/loader.css": productionLoaderCss, "production/logo.svg": productionLogoSvg, "production/safari.png": productionSafariPng, @@ -574,7 +574,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "favicon.ico": {productionFaviconIco, map[string]*bintree{}}, "firefox.png": {productionFirefoxPng, map[string]*bintree{}}, "index.html": {productionIndexHTML, map[string]*bintree{}}, - "index_bundle-2017-01-25T03-10-51Z.js": {productionIndex_bundle20170125t031051zJs, map[string]*bintree{}}, + "index_bundle-2017-01-31T00-38-09Z.js": {productionIndex_bundle20170131t003809zJs, map[string]*bintree{}}, "loader.css": {productionLoaderCss, map[string]*bintree{}}, "logo.svg": {productionLogoSvg, map[string]*bintree{}}, "safari.png": {productionSafariPng, map[string]*bintree{}}, @@ -635,6 +635,6 @@ func assetFS() *assetfs.AssetFS { panic("unreachable") } -var UIReleaseTag = "RELEASE.2017-01-25T03-10-51Z" -var UICommitID = "d41dcb784b4a40639525c27841b9250c123dcb56" -var UIVersion = "2017-01-25T03:10:51Z" +var UIReleaseTag = "RELEASE.2017-01-31T00-38-09Z" +var UICommitID = "e9394dc22df31cdf3ecb63897204ca51b95852a8" +var UIVersion = "2017-01-31T00:38:09Z" From 77a192a7b560f4f7c933280536231996cfb39414 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 31 Jan 2017 09:38:34 -0800 Subject: [PATCH 28/75] Implement CopyObjectPart API (#3663) This API is implemented to allow copying data from an existing source object to an ongoing multipart operation http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html Fixes #3662 --- cmd/api-response.go | 15 ++ cmd/api-router.go | 2 + cmd/benchmark-utils_test.go | 5 +- cmd/fs-v1-multipart.go | 75 ++++++-- cmd/object-api-datatypes.go | 6 +- cmd/object-api-interface.go | 3 +- cmd/object-api-multipart_test.go | 18 +- cmd/object-handlers-common.go | 10 + cmd/object-handlers.go | 126 +++++++++++- cmd/object-handlers_test.go | 318 +++++++++++++++++++++++++++++++ cmd/object_api_suite_test.go | 17 +- cmd/test-utils_test.go | 27 ++- cmd/xl-v1-multipart.go | 83 ++++++-- docs/minio-limitations.md | 1 - 14 files changed, 633 insertions(+), 73 deletions(-) diff --git a/cmd/api-response.go b/cmd/api-response.go index 447a1e732..7f0641bb2 100644 --- a/cmd/api-response.go +++ b/cmd/api-response.go @@ -208,6 +208,13 @@ type CopyObjectResponse struct { ETag string // md5sum of the copied object. } +// CopyObjectPartResponse container returns ETag and LastModified of the successfully copied object +type CopyObjectPartResponse struct { + XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ CopyPartResult" json:"-"` + LastModified string // time string of format "2006-01-02T15:04:05.000Z" + ETag string // md5sum of the copied object part. +} + // Initiator inherit from Owner struct, fields are same type Initiator Owner @@ -399,6 +406,14 @@ func generateCopyObjectResponse(etag string, lastModified time.Time) CopyObjectR } } +// generates CopyObjectPartResponse from etag and lastModified time. +func generateCopyObjectPartResponse(etag string, lastModified time.Time) CopyObjectPartResponse { + return CopyObjectPartResponse{ + ETag: "\"" + etag + "\"", + LastModified: lastModified.UTC().Format(timeFormatAMZLong), + } +} + // generates InitiateMultipartUploadResponse for given bucket, key and uploadID. func generateInitiateMultipartUploadResponse(bucket, key, uploadID string) InitiateMultipartUploadResponse { return InitiateMultipartUploadResponse{ diff --git a/cmd/api-router.go b/cmd/api-router.go index d92aaaa06..b9c76f772 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -40,6 +40,8 @@ func registerAPIRouter(mux *router.Router) { // HeadObject bucket.Methods("HEAD").Path("/{object:.+}").HandlerFunc(api.HeadObjectHandler) + // CopyObjectPart + bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") // PutObjectPart bucket.Methods("PUT").Path("/{object:.+}").HandlerFunc(api.PutObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") // ListObjectPxarts diff --git a/cmd/benchmark-utils_test.go b/cmd/benchmark-utils_test.go index 079fd0cfb..bcd231568 100644 --- a/cmd/benchmark-utils_test.go +++ b/cmd/benchmark-utils_test.go @@ -133,11 +133,12 @@ func runPutObjectPartBenchmark(b *testing.B, obj ObjectLayer, partSize int) { } metadata := make(map[string]string) metadata["md5Sum"] = getMD5Hash([]byte(textPartData)) - md5Sum, err = obj.PutObjectPart(bucket, object, uploadID, j, int64(len(textPartData)), bytes.NewBuffer(textPartData), metadata["md5Sum"], sha256sum) + var partInfo PartInfo + partInfo, err = obj.PutObjectPart(bucket, object, uploadID, j, int64(len(textPartData)), bytes.NewBuffer(textPartData), metadata["md5Sum"], sha256sum) if err != nil { b.Fatal(err) } - if md5Sum != metadata["md5Sum"] { + if partInfo.ETag != metadata["md5Sum"] { b.Fatalf("Write no: %d: Md5Sum mismatch during object write into the bucket: Expected %s, got %s", i+1, md5Sum, metadata["md5Sum"]) } } diff --git a/cmd/fs-v1-multipart.go b/cmd/fs-v1-multipart.go index bc4d398fd..4ae57635c 100644 --- a/cmd/fs-v1-multipart.go +++ b/cmd/fs-v1-multipart.go @@ -451,17 +451,49 @@ func partToAppend(fsMeta fsMetaV1, fsAppendMeta fsMetaV1) (part objectPartInfo, return fsMeta.Parts[nextPartIndex], true } +// CopyObjectPart - similar to PutObjectPart but reads data from an existing +// object. Internally incoming data is written to '.minio.sys/tmp' location +// and safely renamed to '.minio.sys/multipart' for reach parts. +func (fs fsObjects) CopyObjectPart(srcBucket, srcObject, dstBucket, dstObject, uploadID string, partID int, startOffset int64, length int64) (PartInfo, error) { + if err := checkNewMultipartArgs(srcBucket, srcObject, fs); err != nil { + return PartInfo{}, err + } + + // Initialize pipe. + pipeReader, pipeWriter := io.Pipe() + + go func() { + startOffset := int64(0) // Read the whole file. + if gerr := fs.GetObject(srcBucket, srcObject, startOffset, length, pipeWriter); gerr != nil { + errorIf(gerr, "Unable to read %s/%s.", srcBucket, srcObject) + pipeWriter.CloseWithError(gerr) + return + } + pipeWriter.Close() // Close writer explicitly signalling we wrote all data. + }() + + partInfo, err := fs.PutObjectPart(dstBucket, dstObject, uploadID, partID, length, pipeReader, "", "") + if err != nil { + return PartInfo{}, toObjectErr(err, dstBucket, dstObject) + } + + // Explicitly close the reader. + pipeReader.Close() + + return partInfo, nil +} + // PutObjectPart - reads incoming data until EOF for the part file on // an ongoing multipart transaction. Internally incoming data is // written to '.minio.sys/tmp' location and safely renamed to // '.minio.sys/multipart' for reach parts. -func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, size int64, data io.Reader, md5Hex string, sha256sum string) (string, error) { +func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, size int64, data io.Reader, md5Hex string, sha256sum string) (PartInfo, error) { if err := checkPutObjectPartArgs(bucket, object, fs); err != nil { - return "", err + return PartInfo{}, err } if _, err := fs.statBucketDir(bucket); err != nil { - return "", toObjectErr(err, bucket) + return PartInfo{}, toObjectErr(err, bucket) } // Hold the lock so that two parallel complete-multipart-uploads @@ -474,9 +506,9 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s uploadsPath := pathJoin(fs.fsPath, minioMetaMultipartBucket, bucket, object, uploadsJSONFile) if _, err := fs.rwPool.Open(uploadsPath); err != nil { if err == errFileNotFound || err == errFileAccessDenied { - return "", traceError(InvalidUploadID{UploadID: uploadID}) + return PartInfo{}, traceError(InvalidUploadID{UploadID: uploadID}) } - return "", toObjectErr(traceError(err), bucket, object) + return PartInfo{}, toObjectErr(traceError(err), bucket, object) } defer fs.rwPool.Close(uploadsPath) @@ -487,16 +519,16 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s rwlk, err := fs.rwPool.Write(fsMetaPath) if err != nil { if err == errFileNotFound || err == errFileAccessDenied { - return "", traceError(InvalidUploadID{UploadID: uploadID}) + return PartInfo{}, traceError(InvalidUploadID{UploadID: uploadID}) } - return "", toObjectErr(traceError(err), bucket, object) + return PartInfo{}, toObjectErr(traceError(err), bucket, object) } defer rwlk.Close() fsMeta := fsMetaV1{} _, err = fsMeta.ReadFrom(rwlk) if err != nil { - return "", toObjectErr(err, minioMetaMultipartBucket, fsMetaPath) + return PartInfo{}, toObjectErr(err, minioMetaMultipartBucket, fsMetaPath) } partSuffix := fmt.Sprintf("object%d", partID) @@ -534,14 +566,14 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s bytesWritten, cErr := fsCreateFile(fsPartPath, teeReader, buf, size) if cErr != nil { fsRemoveFile(fsPartPath) - return "", toObjectErr(cErr, minioMetaTmpBucket, tmpPartPath) + return PartInfo{}, toObjectErr(cErr, minioMetaTmpBucket, tmpPartPath) } // Should return IncompleteBody{} error when reader has fewer // bytes than specified in request header. if bytesWritten < size { fsRemoveFile(fsPartPath) - return "", traceError(IncompleteBody{}) + return PartInfo{}, traceError(IncompleteBody{}) } // Delete temporary part in case of failure. If @@ -552,14 +584,14 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s newMD5Hex := hex.EncodeToString(md5Writer.Sum(nil)) if md5Hex != "" { if newMD5Hex != md5Hex { - return "", traceError(BadDigest{md5Hex, newMD5Hex}) + return PartInfo{}, traceError(BadDigest{md5Hex, newMD5Hex}) } } if sha256sum != "" { newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)) if newSHA256sum != sha256sum { - return "", traceError(SHA256Mismatch{}) + return PartInfo{}, traceError(SHA256Mismatch{}) } } @@ -572,14 +604,20 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s fsNSPartPath := pathJoin(fs.fsPath, minioMetaMultipartBucket, partPath) if err = fsRenameFile(fsPartPath, fsNSPartPath); err != nil { partLock.Unlock() - return "", toObjectErr(err, minioMetaMultipartBucket, partPath) + return PartInfo{}, toObjectErr(err, minioMetaMultipartBucket, partPath) } // Save the object part info in `fs.json`. fsMeta.AddObjectPart(partID, partSuffix, newMD5Hex, size) if _, err = fsMeta.WriteTo(rwlk); err != nil { partLock.Unlock() - return "", toObjectErr(err, minioMetaMultipartBucket, uploadIDPath) + return PartInfo{}, toObjectErr(err, minioMetaMultipartBucket, uploadIDPath) + } + + partNamePath := pathJoin(fs.fsPath, minioMetaMultipartBucket, uploadIDPath, partSuffix) + fi, err := fsStatFile(partNamePath) + if err != nil { + return PartInfo{}, toObjectErr(err, minioMetaMultipartBucket, partSuffix) } // Append the part in background. @@ -593,7 +631,12 @@ func (fs fsObjects) PutObjectPart(bucket, object, uploadID string, partID int, s partLock.Unlock() }() - return newMD5Hex, nil + return PartInfo{ + PartNumber: partID, + LastModified: fi.ModTime(), + ETag: newMD5Hex, + Size: fi.Size(), + }, nil } // listObjectParts - wrapper scanning through @@ -635,7 +678,7 @@ func (fs fsObjects) listObjectParts(bucket, object, uploadID string, partNumberM if err != nil { return ListPartsInfo{}, toObjectErr(err, minioMetaMultipartBucket, partNamePath) } - result.Parts = append(result.Parts, partInfo{ + result.Parts = append(result.Parts, PartInfo{ PartNumber: part.Number, ETag: part.ETag, LastModified: fi.ModTime(), diff --git a/cmd/object-api-datatypes.go b/cmd/object-api-datatypes.go index 0da114699..cdb052f29 100644 --- a/cmd/object-api-datatypes.go +++ b/cmd/object-api-datatypes.go @@ -145,7 +145,7 @@ type ListPartsInfo struct { IsTruncated bool // List of all parts. - Parts []partInfo + Parts []PartInfo EncodingType string // Not supported yet. } @@ -220,8 +220,8 @@ type ListObjectsInfo struct { Prefixes []string } -// partInfo - represents individual part metadata. -type partInfo struct { +// PartInfo - represents individual part metadata. +type PartInfo struct { // Part number that identifies the part. This is a positive integer between // 1 and 10,000. PartNumber int diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go index 6687d9594..4938af274 100644 --- a/cmd/object-api-interface.go +++ b/cmd/object-api-interface.go @@ -41,7 +41,8 @@ type ObjectLayer interface { // Multipart operations. ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (result ListMultipartsInfo, err error) NewMultipartUpload(bucket, object string, metadata map[string]string) (uploadID string, err error) - PutObjectPart(bucket, object, uploadID string, partID int, size int64, data io.Reader, md5Hex string, sha256sum string) (md5 string, err error) + CopyObjectPart(srcBucket, srcObject, destBucket, destObject string, uploadID string, partID int, startOffset int64, length int64) (info PartInfo, err error) + PutObjectPart(bucket, object, uploadID string, partID int, size int64, data io.Reader, md5Hex string, sha256sum string) (info PartInfo, err error) ListObjectParts(bucket, object, uploadID string, partNumberMarker int, maxParts int) (result ListPartsInfo, err error) AbortMultipartUpload(bucket, object, uploadID string) error CompleteMultipartUpload(bucket, object, uploadID string, uploadedParts []completePart) (objInfo ObjectInfo, err error) diff --git a/cmd/object-api-multipart_test.go b/cmd/object-api-multipart_test.go index 5e0146f3e..5feee0363 100644 --- a/cmd/object-api-multipart_test.go +++ b/cmd/object-api-multipart_test.go @@ -346,7 +346,7 @@ func testObjectAPIPutObjectPart(obj ObjectLayer, instanceType string, t TestErrH // Validate all the test cases. for i, testCase := range testCases { - actualMd5Hex, actualErr := obj.PutObjectPart(testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, testCase.intputDataSize, bytes.NewBufferString(testCase.inputReaderData), testCase.inputMd5, testCase.inputSHA256) + actualInfo, actualErr := obj.PutObjectPart(testCase.bucketName, testCase.objName, testCase.uploadID, testCase.PartID, testCase.intputDataSize, bytes.NewBufferString(testCase.inputReaderData), testCase.inputMd5, testCase.inputSHA256) // All are test cases above are expected to fail. if actualErr != nil && testCase.shouldPass { t.Errorf("Test %d: %s: Expected to pass, but failed with: %s.", i+1, instanceType, actualErr.Error()) @@ -363,8 +363,8 @@ func testObjectAPIPutObjectPart(obj ObjectLayer, instanceType string, t TestErrH // Test passes as expected, but the output values are verified for correctness here. if actualErr == nil && testCase.shouldPass { // Asserting whether the md5 output is correct. - if testCase.inputMd5 != actualMd5Hex { - t.Errorf("Test %d: %s: Calculated Md5 different from the actual one %s.", i+1, instanceType, actualMd5Hex) + if testCase.inputMd5 != actualInfo.ETag { + t.Errorf("Test %d: %s: Calculated Md5 different from the actual one %s.", i+1, instanceType, actualInfo.ETag) } } } @@ -1344,7 +1344,7 @@ func testListObjectPartsDiskNotFound(obj ObjectLayer, instanceType string, disks Object: objectNames[0], MaxParts: 10, UploadID: uploadIDs[0], - Parts: []partInfo{ + Parts: []PartInfo{ { PartNumber: 1, Size: 4, @@ -1375,7 +1375,7 @@ func testListObjectPartsDiskNotFound(obj ObjectLayer, instanceType string, disks NextPartNumberMarker: 3, IsTruncated: true, UploadID: uploadIDs[0], - Parts: []partInfo{ + Parts: []PartInfo{ { PartNumber: 1, Size: 4, @@ -1400,7 +1400,7 @@ func testListObjectPartsDiskNotFound(obj ObjectLayer, instanceType string, disks MaxParts: 2, IsTruncated: false, UploadID: uploadIDs[0], - Parts: []partInfo{ + Parts: []PartInfo{ { PartNumber: 4, Size: 4, @@ -1581,7 +1581,7 @@ func testListObjectParts(obj ObjectLayer, instanceType string, t TestErrHandler) Object: objectNames[0], MaxParts: 10, UploadID: uploadIDs[0], - Parts: []partInfo{ + Parts: []PartInfo{ { PartNumber: 1, Size: 4, @@ -1612,7 +1612,7 @@ func testListObjectParts(obj ObjectLayer, instanceType string, t TestErrHandler) NextPartNumberMarker: 3, IsTruncated: true, UploadID: uploadIDs[0], - Parts: []partInfo{ + Parts: []PartInfo{ { PartNumber: 1, Size: 4, @@ -1637,7 +1637,7 @@ func testListObjectParts(obj ObjectLayer, instanceType string, t TestErrHandler) MaxParts: 2, IsTruncated: false, UploadID: uploadIDs[0], - Parts: []partInfo{ + Parts: []PartInfo{ { PartNumber: 4, Size: 4, diff --git a/cmd/object-handlers-common.go b/cmd/object-handlers-common.go index 46fbe1ec8..dee33a0d5 100644 --- a/cmd/object-handlers-common.go +++ b/cmd/object-handlers-common.go @@ -22,6 +22,16 @@ import ( "time" ) +// Validates the preconditions for CopyObjectPart, returns true if CopyObjectPart +// operation should not proceed. Preconditions supported are: +// x-amz-copy-source-if-modified-since +// x-amz-copy-source-if-unmodified-since +// x-amz-copy-source-if-match +// x-amz-copy-source-if-none-match +func checkCopyObjectPartPreconditions(w http.ResponseWriter, r *http.Request, objInfo ObjectInfo) bool { + return checkCopyObjectPreconditions(w, r, objInfo) +} + // Validates the preconditions for CopyObject, returns true if CopyObject operation should not proceed. // Preconditions supported are: // x-amz-copy-source-if-modified-since diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index d7c2bec79..a3ef52f9f 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -531,7 +531,117 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r writeSuccessResponseXML(w, encodedSuccessResponse) } -// PutObjectPartHandler - Upload part +// CopyObjectPartHandler - uploads a part by copying data from an existing object as data source. +func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + dstBucket := vars["bucket"] + dstObject := vars["object"] + + objectAPI := api.ObjectAPI() + if objectAPI == nil { + writeErrorResponse(w, ErrServerNotInitialized, r.URL) + return + } + + if s3Error := checkRequestAuthType(r, dstBucket, "s3:PutObject", serverConfig.GetRegion()); s3Error != ErrNone { + writeErrorResponse(w, s3Error, r.URL) + return + } + + // Copy source path. + cpSrcPath, err := url.QueryUnescape(r.Header.Get("X-Amz-Copy-Source")) + if err != nil { + // Save unescaped string as is. + cpSrcPath = r.Header.Get("X-Amz-Copy-Source") + } + + srcBucket, srcObject := path2BucketAndObject(cpSrcPath) + // If source object is empty or bucket is empty, reply back invalid copy source. + if srcObject == "" || srcBucket == "" { + writeErrorResponse(w, ErrInvalidCopySource, r.URL) + return + } + + uploadID := r.URL.Query().Get("uploadId") + partIDString := r.URL.Query().Get("partNumber") + + partID, err := strconv.Atoi(partIDString) + if err != nil { + writeErrorResponse(w, ErrInvalidPart, r.URL) + return + } + + // check partID with maximum part ID for multipart objects + if isMaxPartID(partID) { + writeErrorResponse(w, ErrInvalidMaxParts, r.URL) + return + } + + // Hold read locks on source object only if we are + // going to read data from source object. + objectSRLock := globalNSMutex.NewNSLock(srcBucket, srcObject) + objectSRLock.RLock() + defer objectSRLock.RUnlock() + + objInfo, err := objectAPI.GetObjectInfo(srcBucket, srcObject) + if err != nil { + errorIf(err, "Unable to fetch object info.") + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } + + // Get request range. + var hrange *httpRange + rangeHeader := r.Header.Get("x-amz-copy-source-range") + if rangeHeader != "" { + if hrange, err = parseRequestRange(rangeHeader, objInfo.Size); err != nil { + // Handle only errInvalidRange + // Ignore other parse error and treat it as regular Get request like Amazon S3. + if err == errInvalidRange { + writeErrorResponse(w, ErrInvalidRange, r.URL) + return + } + + // log the error. + errorIf(err, "Invalid request range") + } + } + + // Verify before x-amz-copy-source preconditions before continuing with CopyObject. + if checkCopyObjectPartPreconditions(w, r, objInfo) { + return + } + + // Get the object. + startOffset := int64(0) + length := objInfo.Size + if hrange != nil { + startOffset = hrange.offsetBegin + length = hrange.getLength() + } + + /// maximum copy size for multipart objects in a single operation + if isMaxObjectSize(length) { + writeErrorResponse(w, ErrEntityTooLarge, r.URL) + return + } + + // Copy source object to destination, if source and destination + // object is same then only metadata is updated. + partInfo, err := objectAPI.CopyObjectPart(srcBucket, srcObject, dstBucket, dstObject, uploadID, partID, startOffset, length) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } + + response := generateCopyObjectPartResponse(partInfo.ETag, partInfo.LastModified) + encodedSuccessResponse := encodeResponse(response) + + // Write success response. + writeSuccessResponseXML(w, encodedSuccessResponse) +} + +// PutObjectPartHandler - uploads an incoming part for an ongoing multipart operation. func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bucket := vars["bucket"] @@ -590,7 +700,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http return } - var partMD5 string + var partInfo PartInfo incomingMD5 := hex.EncodeToString(md5Bytes) sha256sum := "" switch rAuthType { @@ -606,7 +716,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http return } // No need to verify signature, anonymous request access is already allowed. - partMD5, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum) + partInfo, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum) case authTypeStreamingSigned: // Initialize stream signature verifier. reader, s3Error := newSignV4ChunkedReader(r) @@ -615,7 +725,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http writeErrorResponse(w, s3Error, r.URL) return } - partMD5, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, reader, incomingMD5, sha256sum) + partInfo, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, reader, incomingMD5, sha256sum) case authTypeSignedV2, authTypePresignedV2: s3Error := isReqAuthenticatedV2(r) if s3Error != ErrNone { @@ -623,7 +733,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http writeErrorResponse(w, s3Error, r.URL) return } - partMD5, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum) + partInfo, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum) case authTypePresigned, authTypeSigned: if s3Error := reqSignatureV4Verify(r); s3Error != ErrNone { errorIf(errSignatureMismatch, dumpRequest(r)) @@ -634,7 +744,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http if !skipContentSha256Cksum(r) { sha256sum = r.Header.Get("X-Amz-Content-Sha256") } - partMD5, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum) + partInfo, err = objectAPI.PutObjectPart(bucket, object, uploadID, partID, size, r.Body, incomingMD5, sha256sum) } if err != nil { errorIf(err, "Unable to create object part.") @@ -642,8 +752,8 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } - if partMD5 != "" { - w.Header().Set("ETag", "\""+partMD5+"\"") + if partInfo.ETag != "" { + w.Header().Set("ETag", "\""+partInfo.ETag+"\"") } writeSuccessResponseHeadersOnly(w) diff --git a/cmd/object-handlers_test.go b/cmd/object-handlers_test.go index ed454fd87..5d0359d0c 100644 --- a/cmd/object-handlers_test.go +++ b/cmd/object-handlers_test.go @@ -918,6 +918,324 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a } +// Wrapper for calling Copy Object Part API handler tests for both XL multiple disks and single node setup. +func TestAPICopyObjectPartHandler(t *testing.T) { + defer DetectTestLeak(t)() + ExecObjectLayerAPITest(t, testAPICopyObjectPartHandler, []string{"CopyObjectPart"}) +} + +func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, + credentials credential, t *testing.T) { + + objectName := "test-object" + // register event notifier. + err := initEventNotifier(obj) + if err != nil { + t.Fatalf("Initializing event notifiers failed") + } + + // set of byte data for PutObject. + // object has to be created before running tests for Copy Object. + // this is required even to assert the copied object, + bytesData := []struct { + byteData []byte + }{ + {generateBytesData(6 * humanize.KiByte)}, + } + + // set of inputs for uploading the objects before tests for downloading is done. + putObjectInputs := []struct { + bucketName string + objectName string + contentLength int64 + textData []byte + metaData map[string]string + }{ + // case - 1. + {bucketName, objectName, int64(len(bytesData[0].byteData)), bytesData[0].byteData, make(map[string]string)}, + } + sha256sum := "" + // iterate through the above set of inputs and upload the object. + for i, input := range putObjectInputs { + // uploading the object. + _, err = obj.PutObject(input.bucketName, input.objectName, input.contentLength, bytes.NewBuffer(input.textData), input.metaData, sha256sum) + // if object upload fails stop the test. + if err != nil { + t.Fatalf("Put Object case %d: Error uploading object: %v", i+1, err) + } + } + + // Initiate Multipart upload for testing PutObjectPartHandler. + testObject := "testobject" + + // PutObjectPart API HTTP Handler has to be tested in isolation, + // that is without any other handler being registered, + // That's why NewMultipartUpload is initiated using ObjectLayer. + uploadID, err := obj.NewMultipartUpload(bucketName, testObject, nil) + if err != nil { + // Failed to create NewMultipartUpload, abort. + t.Fatalf("Minio %s : %s", instanceType, err) + } + + // test cases with inputs and expected result for Copy Object. + testCases := []struct { + bucketName string + copySourceHeader string // data for "X-Amz-Copy-Source" header. Contains the object to be copied in the URL. + copySourceRange string // data for "X-Amz-Copy-Source-Range" header, contains the byte range offsets of data to be copied. + uploadID string // uploadID of the transaction. + invalidPartNumber bool // Sets an invalid multipart. + maximumPartNumber bool // Sets a maximum parts. + accessKey string + secretKey string + // expected output. + expectedRespStatus int + }{ + // Test case - 1, copy part 1 from from newObject1, ignore request headers. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + expectedRespStatus: http.StatusOK, + }, + + // Test case - 2. + // Test case with invalid source object. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/"), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusBadRequest, + }, + + // Test case - 3. + // Test case with new object name is same as object to be copied. + // Fail with file not found. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + testObject), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusNotFound, + }, + + // Test case - 4. + // Test case with valid byte range. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceRange: "bytes=500-4096", + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusOK, + }, + + // Test case - 5. + // Test case with invalid byte range. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + copySourceRange: "bytes=6145-", + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusRequestedRangeNotSatisfiable, + }, + + // Test case - 6. + // Test case with object name missing from source. + // fail with BadRequest. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("//123"), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusBadRequest, + }, + + // Test case - 7. + // Test case with non-existent source file. + // Case for the purpose of failing `api.ObjectAPI.GetObjectInfo`. + // Expecting the response status code to http.StatusNotFound (404). + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + "non-existent-object"), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusNotFound, + }, + + // Test case - 8. + // Test case with non-existent source file. + // Case for the purpose of failing `api.ObjectAPI.PutObjectPart`. + // Expecting the response status code to http.StatusNotFound (404). + { + bucketName: "non-existent-destination-bucket", + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusNotFound, + }, + + // Test case - 9. + // Case with invalid AccessKey. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + accessKey: "Invalid-AccessID", + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusForbidden, + }, + + // Test case - 10. + // Case with non-existent upload id. + { + bucketName: bucketName, + uploadID: "-1", + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + + expectedRespStatus: http.StatusNotFound, + }, + // Test case - 11. + // invalid part number. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + invalidPartNumber: true, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + expectedRespStatus: http.StatusOK, + }, + // Test case - 12. + // maximum part number. + { + bucketName: bucketName, + uploadID: uploadID, + copySourceHeader: url.QueryEscape("/" + bucketName + "/" + objectName), + maximumPartNumber: true, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + expectedRespStatus: http.StatusOK, + }, + } + + for i, testCase := range testCases { + var req *http.Request + var reqV2 *http.Request + // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. + rec := httptest.NewRecorder() + if !testCase.invalidPartNumber || !testCase.maximumPartNumber { + // construct HTTP request for copy object. + req, err = newTestSignedRequestV4("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "1"), 0, nil, testCase.accessKey, testCase.secretKey) + } else if testCase.invalidPartNumber { + req, err = newTestSignedRequestV4("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "abc"), 0, nil, testCase.accessKey, testCase.secretKey) + } else if testCase.maximumPartNumber { + req, err = newTestSignedRequestV4("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "99999"), 0, nil, testCase.accessKey, testCase.secretKey) + } + if err != nil { + t.Fatalf("Test %d: Failed to create HTTP request for copy Object: %v", i+1, err) + } + + // "X-Amz-Copy-Source" header contains the information about the source bucket and the object to copied. + if testCase.copySourceHeader != "" { + req.Header.Set("X-Amz-Copy-Source", testCase.copySourceHeader) + } + if testCase.copySourceRange != "" { + req.Header.Set("X-Amz-Copy-Source-Range", testCase.copySourceRange) + } + // Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler. + // Call the ServeHTTP to execute the handler, `func (api objectAPIHandlers) CopyObjectHandler` handles the request. + apiRouter.ServeHTTP(rec, req) + // Assert the response code with the expected status. + if rec.Code != testCase.expectedRespStatus { + t.Fatalf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, rec.Code) + } + if rec.Code == http.StatusOK { + // See if the new part has been uploaded. + // testing whether the copy was successful. + var results ListPartsInfo + results, err = obj.ListObjectParts(testCase.bucketName, testObject, testCase.uploadID, 0, 1) + if err != nil { + t.Fatalf("Test %d: %s: Failed to look for copied object part: %s", i+1, instanceType, err) + } + if len(results.Parts) != 1 { + t.Fatalf("Test %d: %s: Expected only one entry returned %d entries", i+1, instanceType, len(results.Parts)) + } + } + + // Verify response of the V2 signed HTTP request. + // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. + recV2 := httptest.NewRecorder() + + reqV2, err = newTestRequest("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "1"), 0, nil) + if err != nil { + t.Fatalf("Test %d: Failed to create HTTP request for copy Object: %v", i+1, err) + } + // "X-Amz-Copy-Source" header contains the information about the source bucket and the object to copied. + if testCase.copySourceHeader != "" { + reqV2.Header.Set("X-Amz-Copy-Source", testCase.copySourceHeader) + } + if testCase.copySourceRange != "" { + reqV2.Header.Set("X-Amz-Copy-Source-Range", testCase.copySourceRange) + } + + err = signRequestV2(reqV2, testCase.accessKey, testCase.secretKey) + if err != nil { + t.Fatalf("Failed to V2 Sign the HTTP request: %v.", err) + } + + // Since `apiRouter` satisfies `http.Handler` it has a ServeHTTP to execute the logic of the handler. + // Call the ServeHTTP to execute the handler. + apiRouter.ServeHTTP(recV2, reqV2) + if recV2.Code != testCase.expectedRespStatus { + t.Errorf("Test %d: %s: Expected the response status to be `%d`, but instead found `%d`", i+1, instanceType, testCase.expectedRespStatus, recV2.Code) + } + } + + // HTTP request for testing when `ObjectLayer` is set to `nil`. + // There is no need to use an existing bucket and valid input for creating the request + // since the `objectLayer==nil` check is performed before any other checks inside the handlers. + // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. + nilBucket := "dummy-bucket" + nilObject := "dummy-object" + + nilReq, err := newTestSignedRequestV4("PUT", getCopyObjectPartURL("", nilBucket, nilObject, "0", "0"), + 0, bytes.NewReader([]byte("testNilObjLayer")), "", "") + if err != nil { + t.Errorf("Minio %s: Failed to create http request for testing the response when object Layer is set to `nil`.", instanceType) + } + + // Below is how CopyObjectPartHandler is registered. + // bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") + // Its necessary to set the "X-Amz-Copy-Source" header for the request to be accepted by the handler. + nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape("/"+nilBucket+"/"+nilObject)) + + // execute the object layer set to `nil` test. + // `ExecObjectLayerAPINilTest` manages the operation. + ExecObjectLayerAPINilTest(t, nilBucket, nilObject, instanceType, apiRouter, nilReq) + +} + // Wrapper for calling Copy Object API handler tests for both XL multiple disks and single node setup. func TestAPICopyObjectHandler(t *testing.T) { defer DetectTestLeak(t)() diff --git a/cmd/object_api_suite_test.go b/cmd/object_api_suite_test.go index 88ad87964..e3cb467ad 100644 --- a/cmd/object_api_suite_test.go +++ b/cmd/object_api_suite_test.go @@ -106,15 +106,18 @@ func testMultipartObjectCreation(obj ObjectLayer, instanceType string, c TestErr for i := 1; i <= 10; i++ { expectedMD5Sumhex := getMD5Hash(data) - var calculatedMD5sum string - calculatedMD5sum, err = obj.PutObjectPart("bucket", "key", uploadID, i, int64(len(data)), bytes.NewBuffer(data), expectedMD5Sumhex, "") + var calcPartInfo PartInfo + calcPartInfo, err = obj.PutObjectPart("bucket", "key", uploadID, i, int64(len(data)), bytes.NewBuffer(data), expectedMD5Sumhex, "") if err != nil { c.Errorf("%s: %s", instanceType, err) } - if calculatedMD5sum != expectedMD5Sumhex { + if calcPartInfo.ETag != expectedMD5Sumhex { c.Errorf("MD5 Mismatch") } - completedParts.Parts = append(completedParts.Parts, completePart{PartNumber: i, ETag: calculatedMD5sum}) + completedParts.Parts = append(completedParts.Parts, completePart{ + PartNumber: i, + ETag: calcPartInfo.ETag, + }) } objInfo, err := obj.CompleteMultipartUpload("bucket", "key", uploadID, completedParts.Parts) if err != nil { @@ -153,12 +156,12 @@ func testMultipartObjectAbort(obj ObjectLayer, instanceType string, c TestErrHan expectedMD5Sumhex := getMD5Hash([]byte(randomString)) metadata["md5"] = expectedMD5Sumhex - var calculatedMD5sum string - calculatedMD5sum, err = obj.PutObjectPart("bucket", "key", uploadID, i, int64(len(randomString)), bytes.NewBufferString(randomString), expectedMD5Sumhex, "") + var calcPartInfo PartInfo + calcPartInfo, err = obj.PutObjectPart("bucket", "key", uploadID, i, int64(len(randomString)), bytes.NewBufferString(randomString), expectedMD5Sumhex, "") if err != nil { c.Fatalf("%s: %s", instanceType, err) } - if calculatedMD5sum != expectedMD5Sumhex { + if calcPartInfo.ETag != expectedMD5Sumhex { c.Errorf("Md5 Mismatch") } parts[i] = expectedMD5Sumhex diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index a9c544576..98c6bc15e 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -1419,6 +1419,13 @@ func getPutObjectPartURL(endPoint, bucketName, objectName, uploadID, partNumber return makeTestTargetURL(endPoint, bucketName, objectName, queryValues) } +func getCopyObjectPartURL(endPoint, bucketName, objectName, uploadID, partNumber string) string { + queryValues := url.Values{} + queryValues.Set("uploadId", uploadID) + queryValues.Set("partNumber", partNumber) + return makeTestTargetURL(endPoint, bucketName, objectName, queryValues) +} + // return URL for fetching object from the bucket. func getGetObjectURL(endPoint, bucketName, objectName string) string { return makeTestTargetURL(endPoint, bucketName, objectName, url.Values{}) @@ -1883,22 +1890,22 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, } } -// ExecObjectLayerAPINilTest - Sets the object layer to `nil`, and calls rhe registered object layer API endpoint, and assert the error response. -// The purpose is to validate the API handlers response when the object layer is uninitialized. -// Usage hint: Should be used at the end of the API end points tests (ex: check the last few lines of `testAPIListObjectPartsHandler`), need a sample HTTP request -// to be sent as argument so that the relevant handler is called, -// the handler registration is expected to be done since its called from within the API handler tests, -// the reference to the registered HTTP handler has to be sent as an argument. +// ExecObjectLayerAPINilTest - Sets the object layer to `nil`, and calls rhe registered object layer API endpoint, +// and assert the error response. The purpose is to validate the API handlers response when the object layer is uninitialized. +// Usage hint: Should be used at the end of the API end points tests (ex: check the last few lines of `testAPIListObjectPartsHandler`), +// need a sample HTTP request to be sent as argument so that the relevant handler is called, the handler registration is expected +// to be done since its called from within the API handler tests, the reference to the registered HTTP handler has to be sent +// as an argument. func ExecObjectLayerAPINilTest(t TestErrHandler, bucketName, objectName, instanceType string, apiRouter http.Handler, req *http.Request) { // httptest Recorder to capture all the response by the http handler. rec := httptest.NewRecorder() // The API handler gets the referece to the object layer via the global object Layer, // setting it to `nil` in order test for handlers response for uninitialized object layer. - globalObjLayerMutex.Lock() globalObjectAPI = nil globalObjLayerMutex.Unlock() + // call the HTTP handler. apiRouter.ServeHTTP(rec, req) @@ -1909,7 +1916,8 @@ func ExecObjectLayerAPINilTest(t TestErrHandler, bucketName, objectName, instanc t.Errorf("Object API Nil Test expected to fail with %d, but failed with %d", serverNotInitializedErr, rec.Code) } // expected error response in bytes when objectLayer is not initialized, or set to `nil`. - expectedErrResponse := encodeResponse(getAPIErrorResponse(getAPIError(ErrServerNotInitialized), getGetObjectURL("", bucketName, objectName))) + expectedErrResponse := encodeResponse(getAPIErrorResponse(getAPIError(ErrServerNotInitialized), + getGetObjectURL("", bucketName, objectName))) // HEAD HTTP Request doesn't contain body in its response, // for other type of HTTP requests compare the response body content with the expected one. @@ -2093,6 +2101,9 @@ func registerBucketLevelFunc(bucket *router.Router, api objectAPIHandlers, apiFu case "NewMultipart": // Register New Multipart upload handler. bucket.Methods("POST").Path("/{object:.+}").HandlerFunc(api.NewMultipartUploadHandler).Queries("uploads", "") + case "CopyObjectPart": + // Register CopyObjectPart handler. + bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") case "PutObjectPart": // Register PutObjectPart handler. bucket.Methods("PUT").Path("/{object:.+}").HandlerFunc(api.PutObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") diff --git a/cmd/xl-v1-multipart.go b/cmd/xl-v1-multipart.go index 10fd79f1f..cbaa58f7f 100644 --- a/cmd/xl-v1-multipart.go +++ b/cmd/xl-v1-multipart.go @@ -499,7 +499,8 @@ func (xl xlObjects) newMultipartUpload(bucket string, object string, meta map[st uploadIDPath := path.Join(bucket, object, uploadID) tempUploadIDPath := uploadID // Write updated `xl.json` to all disks. - if err := writeSameXLMetadata(xl.storageDisks, minioMetaTmpBucket, tempUploadIDPath, xlMeta, xl.writeQuorum, xl.readQuorum); err != nil { + err := writeSameXLMetadata(xl.storageDisks, minioMetaTmpBucket, tempUploadIDPath, xlMeta, xl.writeQuorum, xl.readQuorum) + if err != nil { return "", toObjectErr(err, minioMetaTmpBucket, tempUploadIDPath) } // delete the tmp path later in case we fail to rename (ignore @@ -538,14 +539,49 @@ func (xl xlObjects) NewMultipartUpload(bucket, object string, meta map[string]st return xl.newMultipartUpload(bucket, object, meta) } +// CopyObjectPart - reads incoming stream and internally erasure codes +// them. This call is similar to put object part operation but the source +// data is read from an existing object. +// +// Implements S3 compatible Upload Part Copy API. +func (xl xlObjects) CopyObjectPart(srcBucket, srcObject, dstBucket, dstObject, uploadID string, partID int, startOffset int64, length int64) (PartInfo, error) { + if err := checkNewMultipartArgs(srcBucket, srcObject, xl); err != nil { + return PartInfo{}, err + } + + // Initialize pipe. + pipeReader, pipeWriter := io.Pipe() + + go func() { + startOffset := int64(0) // Read the whole file. + if gerr := xl.GetObject(srcBucket, srcObject, startOffset, length, pipeWriter); gerr != nil { + errorIf(gerr, "Unable to read %s of the object `%s/%s`.", srcBucket, srcObject) + pipeWriter.CloseWithError(toObjectErr(gerr, srcBucket, srcObject)) + return + } + pipeWriter.Close() // Close writer explicitly signalling we wrote all data. + }() + + partInfo, err := xl.PutObjectPart(dstBucket, dstObject, uploadID, partID, length, pipeReader, "", "") + if err != nil { + return PartInfo{}, toObjectErr(err, dstBucket, dstObject) + } + + // Explicitly close the reader. + pipeReader.Close() + + // Success. + return partInfo, nil +} + // PutObjectPart - reads incoming stream and internally erasure codes // them. This call is similar to single put operation but it is part // of the multipart transaction. // // Implements S3 compatible Upload Part API. -func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, size int64, data io.Reader, md5Hex string, sha256sum string) (string, error) { +func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, size int64, data io.Reader, md5Hex string, sha256sum string) (PartInfo, error) { if err := checkPutObjectPartArgs(bucket, object, xl); err != nil { - return "", err + return PartInfo{}, err } var partsMetadata []xlMetaV1 @@ -558,14 +594,15 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Validates if upload ID exists. if !xl.isUploadIDExists(bucket, object, uploadID) { preUploadIDLock.RUnlock() - return "", traceError(InvalidUploadID{UploadID: uploadID}) + return PartInfo{}, traceError(InvalidUploadID{UploadID: uploadID}) } + // Read metadata associated with the object from all disks. partsMetadata, errs = readAllXLMetadata(xl.storageDisks, minioMetaMultipartBucket, uploadIDPath) if !isDiskQuorum(errs, xl.writeQuorum) { preUploadIDLock.RUnlock() - return "", toObjectErr(traceError(errXLWriteQuorum), bucket, object) + return PartInfo{}, toObjectErr(traceError(errXLWriteQuorum), bucket, object) } preUploadIDLock.RUnlock() @@ -575,7 +612,7 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Pick one from the first valid metadata. xlMeta, err := pickValidXLMeta(partsMetadata, modTime) if err != nil { - return "", err + return PartInfo{}, err } onlineDisks = getOrderedDisks(xlMeta.Erasure.Distribution, onlineDisks) @@ -633,13 +670,13 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Erasure code data and write across all disks. sizeWritten, checkSums, err := erasureCreateFile(onlineDisks, minioMetaTmpBucket, tmpPartPath, teeReader, allowEmpty, xlMeta.Erasure.BlockSize, xl.dataBlocks, xl.parityBlocks, bitRotAlgo, xl.writeQuorum) if err != nil { - return "", toObjectErr(err, bucket, object) + return PartInfo{}, toObjectErr(err, bucket, object) } // Should return IncompleteBody{} error when reader has fewer bytes // than specified in request header. if sizeWritten < size { - return "", traceError(IncompleteBody{}) + return PartInfo{}, traceError(IncompleteBody{}) } // For size == -1, perhaps client is sending in chunked encoding @@ -653,14 +690,14 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s if md5Hex != "" { if newMD5Hex != md5Hex { // Returns md5 mismatch. - return "", traceError(BadDigest{md5Hex, newMD5Hex}) + return PartInfo{}, traceError(BadDigest{md5Hex, newMD5Hex}) } } if sha256sum != "" { newSHA256sum := hex.EncodeToString(sha256Writer.Sum(nil)) if newSHA256sum != sha256sum { - return "", traceError(SHA256Mismatch{}) + return PartInfo{}, traceError(SHA256Mismatch{}) } } @@ -671,20 +708,20 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Validate again if upload ID still exists. if !xl.isUploadIDExists(bucket, object, uploadID) { - return "", traceError(InvalidUploadID{UploadID: uploadID}) + return PartInfo{}, traceError(InvalidUploadID{UploadID: uploadID}) } // Rename temporary part file to its final location. partPath := path.Join(uploadIDPath, partSuffix) err = renamePart(onlineDisks, minioMetaTmpBucket, tmpPartPath, minioMetaMultipartBucket, partPath, xl.writeQuorum) if err != nil { - return "", toObjectErr(err, minioMetaMultipartBucket, partPath) + return PartInfo{}, toObjectErr(err, minioMetaMultipartBucket, partPath) } // Read metadata again because it might be updated with parallel upload of another part. partsMetadata, errs = readAllXLMetadata(onlineDisks, minioMetaMultipartBucket, uploadIDPath) if !isDiskQuorum(errs, xl.writeQuorum) { - return "", toObjectErr(traceError(errXLWriteQuorum), bucket, object) + return PartInfo{}, toObjectErr(traceError(errXLWriteQuorum), bucket, object) } // Get current highest version based on re-read partsMetadata. @@ -693,7 +730,7 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Pick one from the first valid metadata. xlMeta, err = pickValidXLMeta(partsMetadata, modTime) if err != nil { - return "", err + return PartInfo{}, err } // Once part is successfully committed, proceed with updating XL metadata. @@ -720,15 +757,25 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Writes a unique `xl.json` each disk carrying new checksum related information. if err = writeUniqueXLMetadata(onlineDisks, minioMetaTmpBucket, tempXLMetaPath, partsMetadata, xl.writeQuorum); err != nil { - return "", toObjectErr(err, minioMetaTmpBucket, tempXLMetaPath) + return PartInfo{}, toObjectErr(err, minioMetaTmpBucket, tempXLMetaPath) } rErr := commitXLMetadata(onlineDisks, minioMetaTmpBucket, tempXLMetaPath, minioMetaMultipartBucket, uploadIDPath, xl.writeQuorum) if rErr != nil { - return "", toObjectErr(rErr, minioMetaMultipartBucket, uploadIDPath) + return PartInfo{}, toObjectErr(rErr, minioMetaMultipartBucket, uploadIDPath) + } + + fi, err := xl.statPart(bucket, object, uploadID, partSuffix) + if err != nil { + return PartInfo{}, toObjectErr(rErr, minioMetaMultipartBucket, partSuffix) } // Return success. - return newMD5Hex, nil + return PartInfo{ + PartNumber: partID, + LastModified: fi.ModTime, + ETag: newMD5Hex, + Size: fi.Size, + }, nil } // listObjectParts - wrapper reading `xl.json` for a given object and @@ -772,7 +819,7 @@ func (xl xlObjects) listObjectParts(bucket, object, uploadID string, partNumberM if err != nil { return ListPartsInfo{}, toObjectErr(err, minioMetaBucket, path.Join(uploadID, part.Name)) } - result.Parts = append(result.Parts, partInfo{ + result.Parts = append(result.Parts, PartInfo{ PartNumber: part.Number, ETag: part.ETag, LastModified: fi.ModTime, diff --git a/docs/minio-limitations.md b/docs/minio-limitations.md index 539e6ef9f..d7f49e660 100644 --- a/docs/minio-limitations.md +++ b/docs/minio-limitations.md @@ -47,4 +47,3 @@ We found the following APIs to be redundant or less useful outside of AWS. If yo - ObjectACL (Use bucket policies instead) - ObjectTorrent -- ObjectCopyPart From f7f103725b509d6bcff772d3de1ee60593c49492 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Tue, 31 Jan 2017 13:44:07 -0800 Subject: [PATCH 29/75] browser: Make logo and "Minio Browser" text non-clickable. (#3668) fixes #3601 --- browser/app/js/components/Browse.js | 8 +------- browser/app/js/components/SideBar.js | 6 +++--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/browser/app/js/components/Browse.js b/browser/app/js/components/Browse.js index 4c2343762..128b6c8c2 100644 --- a/browser/app/js/components/Browse.js +++ b/browser/app/js/components/Browse.js @@ -296,11 +296,6 @@ export default class Browse extends React.Component { browserHistory.push(`${minioBrowserPrefix}/login`) } - landingPage(e) { - e.preventDefault() - this.props.dispatch(actions.selectBucket(this.props.buckets[0])) - } - fullScreen(e) { e.preventDefault() let el = document.documentElement @@ -489,8 +484,7 @@ export default class Browse extends React.Component { 'file-explorer': true, 'toggled': sidebarStatus }) }> - diff --git a/browser/app/js/components/SideBar.js b/browser/app/js/components/SideBar.js index ad4aee576..d92bfbceb 100644 --- a/browser/app/js/components/SideBar.js +++ b/browser/app/js/components/SideBar.js @@ -22,7 +22,7 @@ import connect from 'react-redux/lib/components/connect' import logo from '../../img/logo.svg' -let SideBar = ({visibleBuckets, loadBucket, currentBucket, selectBucket, searchBuckets, landingPage, sidebarStatus, clickOutside, showPolicy}) => { +let SideBar = ({visibleBuckets, loadBucket, currentBucket, selectBucket, searchBuckets, sidebarStatus, clickOutside, showPolicy}) => { const list = visibleBuckets.map((bucket, i) => { return
  • - -

    Minio Browser

    + +

    Minio Browser

    From 1b30a3be2b9a7774083b11ae1b37625e9cf42530 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 31 Jan 2017 15:34:49 -0800 Subject: [PATCH 30/75] xl/utils: getPartSizeFromIdx should return error. (#3669) --- cmd/xl-v1-object.go | 18 ++++++++++++++++-- cmd/xl-v1-utils.go | 21 ++++++++++++++------- cmd/xl-v1-utils_test.go | 28 ++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index 86563d362..d25c41d2e 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -542,7 +542,11 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. // Calculate the size of the current part, if size is unknown, curPartSize wil be unknown too. // allowEmptyPart will always be true if this is the first part and false otherwise. - curPartSize := getPartSizeFromIdx(size, globalPutPartSize, partIdx) + var curPartSize int64 + curPartSize, err = getPartSizeFromIdx(size, globalPutPartSize, partIdx) + if err != nil { + return ObjectInfo{}, toObjectErr(err, bucket, object) + } // Prepare file for eventual optimization in the disk if curPartSize > 0 { @@ -593,7 +597,17 @@ func (xl xlObjects) PutObject(bucket string, object string, size int64, data io. // If we didn't write anything or we know that the next part doesn't have any // data to write, we should quit this loop immediately - if partSizeWritten == 0 || getPartSizeFromIdx(size, globalPutPartSize, partIdx+1) == 0 { + if partSizeWritten == 0 { + break + } + + // Check part size for the next index. + var partSize int64 + partSize, err = getPartSizeFromIdx(size, globalPutPartSize, partIdx+1) + if err != nil { + return ObjectInfo{}, toObjectErr(err, bucket, object) + } + if partSize == 0 { break } } diff --git a/cmd/xl-v1-utils.go b/cmd/xl-v1-utils.go index 536eae968..4a40fdae7 100644 --- a/cmd/xl-v1-utils.go +++ b/cmd/xl-v1-utils.go @@ -17,6 +17,7 @@ package cmd import ( + "errors" "hash/crc32" "path" "sync" @@ -344,29 +345,35 @@ func getOrderedDisks(distribution []int, disks []StorageAPI) (orderedDisks []Sto return orderedDisks } +// Errors specifically generated by getPartSizeFromIdx function. +var ( + errPartSizeZero = errors.New("Part size cannot be zero") + errPartSizeIndex = errors.New("Part index cannot be smaller than 1") +) + // getPartSizeFromIdx predicts the part size according to its index. It also // returns -1 when totalSize is also -1. -func getPartSizeFromIdx(totalSize int64, partSize int64, partIndex int) int64 { +func getPartSizeFromIdx(totalSize int64, partSize int64, partIndex int) (int64, error) { if partSize == 0 { - panic("Part size cannot be nil.") + return 0, traceError(errPartSizeZero) } if partIndex < 1 { - panic("Part index should be greater than 1.") + return 0, traceError(errPartSizeIndex) } switch totalSize { case -1, 0: - return totalSize + return totalSize, nil } // Compute the total count of parts partsCount := totalSize/partSize + 1 // Return the part's size switch { case int64(partIndex) < partsCount: - return partSize + return partSize, nil case int64(partIndex) == partsCount: // Size of last part - return totalSize % partSize + return totalSize % partSize, nil default: - return 0 + return 0, nil } } diff --git a/cmd/xl-v1-utils_test.go b/cmd/xl-v1-utils_test.go index 4b80ffbb4..bf6f2205b 100644 --- a/cmd/xl-v1-utils_test.go +++ b/cmd/xl-v1-utils_test.go @@ -353,9 +353,33 @@ func TestGetPartSizeFromIdx(t *testing.T) { } for i, testCase := range testCases { - s := getPartSizeFromIdx(testCase.totalSize, testCase.partSize, testCase.partIndex) - if s != testCase.expectedSize { + s, err := getPartSizeFromIdx(testCase.totalSize, testCase.partSize, testCase.partIndex) + if err != nil { + t.Errorf("Test %d: Expected to pass but failed. %s", i+1, err) + } + if err == nil && s != testCase.expectedSize { t.Errorf("Test %d: The calculated part size is incorrect: expected = %d, found = %d\n", i+1, testCase.expectedSize, s) } } + + testCasesFailure := []struct { + totalSize int64 + partSize int64 + partIndex int + err error + }{ + // partSize is 0, error. + {10, 0, 1, errPartSizeZero}, + {10, 1, 0, errPartSizeIndex}, + } + + for i, testCaseFailure := range testCasesFailure { + _, err := getPartSizeFromIdx(testCaseFailure.totalSize, testCaseFailure.partSize, testCaseFailure.partIndex) + if err == nil { + t.Errorf("Test %d: Expected to failed but passed. %s", i+1, err) + } + if err != nil && errorCause(err) != testCaseFailure.err { + t.Errorf("Test %d: Expected err %s, but got %s", i+1, testCaseFailure.err, errorCause(err)) + } + } } From 4dea4f3b891494cb07ace6fc6c9051435df8e07b Mon Sep 17 00:00:00 2001 From: koolhead17 Date: Wed, 1 Feb 2017 06:34:36 +0530 Subject: [PATCH 31/75] docs: added event-notification back end doc. (#3510) --- docs/bucket-notifications/README.md | 477 ++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 docs/bucket-notifications/README.md diff --git a/docs/bucket-notifications/README.md b/docs/bucket-notifications/README.md new file mode 100644 index 000000000..6d3fab028 --- /dev/null +++ b/docs/bucket-notifications/README.md @@ -0,0 +1,477 @@ +[![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) + +Minio server supports Amazon S3 compatible bucket event notification for the following targets [AMQP](https://www.amqp.org/about/what), [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html) , [Redis](http://redis.io/documentation), [nats.io](http://nats.io/), [PostgreSQL](https://www.postgresql.org) and [kafka](https://kafka.apache.org/). + +## Prerequisites + +* Install and configure Minio Server from [here](http://docs.minio.io/docs/minio). +* Install and configure Minio Client from [here](https://docs.minio.io/docs/minio-client-quickstart-guide). + +| Notification Targets| +|:-- +| [`RabbitMQ`](#RabbitMQ) | +| [`Elasticsearch`](#Elasticsearch) | +| [`Redis`](#Redis) | +| [`NATS`](#NATS) | +| [`PostgreSQL`](#PostgreSQL) | +| [`kafka`](#kafka) | + + +## Publish Minio events via RabbitMQ + +Install RabbitMQ from [here](https://www.rabbitmq.com/). + +### Recipe steps + +### Step 1: Add RabbitMQ endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the RabbitMQ configuration block in ``config.json`` as follows: + +``` +"amqp": { + "1": { + "enable": true, + "url": "amqp://myuser:mypassword@localhost:5672", + "exchange": "bucketevents", + "routingKey": "bucketlogs", + "exchangeType": "fanout", + "mandatory": false, + "immediate": false, + "durable": false, + "internal": false, + "noWait": false, + "autoDeleted": false + } + } +``` +Restart Minio server to reflect config changes. Minio supports all the exchange available in [RabbitMQ](https://www.rabbitmq.com/). For this setup, we are using ``fanout`` exchange. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded or deleted ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:amqp``. To understand more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc events add myminio/images arn:minio:sqs:us-east-1:1:amqp --suffix .jpg +mc events list myminio/images +arn:minio:sqs:us-east-1:1:amqp s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” +``` + +### Step 3: Test on RabbitMQ + +The python program below waits on the queue exchange ``bucketevents`` and prints event notifications on the console. We use [Pika Python Client](https://www.rabbitmq.com/tutorials/tutorial-three-python.html) library to do this. + +```py +#!/usr/bin/env python +import pika + +connection = pika.BlockingConnection(pika.ConnectionParameters( + host='localhost')) +channel = connection.channel() + +channel.exchange_declare(exchange='bucketevents', + type='fanout') + +result = channel.queue_declare(exclusive=False) +queue_name = result.method.queue + +channel.queue_bind(exchange='bucketevents', + queue=queue_name) + +print(' [*] Waiting for logs. To exit press CTRL+C') + +def callback(ch, method, properties, body): + print(" [x] %r" % body) + +channel.basic_consume(callback, + queue=queue_name, + no_ack=False) + +channel.start_consuming() +``` + +Execute this example python program to watch for RabbitMQ events on the console. + +```py +python rabbit.py +``` + +Open another terminal and upload a JPEG image into ``images`` bucket. + +``` +mc cp myphoto.jpg myminio/images +``` + +You should receive the following event notification via RabbitMQ once the upload completes. + +```py +python rabbit.py +‘{“Records”:[{“eventVersion”:”2.0",”eventSource”:”aws:s3",”awsRegion”:”us-east-1",”eventTime”:”2016–09–08T22:34:38.226Z”,”eventName”:”s3:ObjectCreated:Put”,”userIdentity”:{“principalId”:”minio”},”requestParameters”:{“sourceIPAddress”:”10.1.10.150:44576"},”responseElements”:{},”s3":{“s3SchemaVersion”:”1.0",”configurationId”:”Config”,”bucket”:{“name”:”images”,”ownerIdentity”:{“principalId”:”minio”},”arn”:”arn:aws:s3:::images”},”object”:{“key”:”myphoto.jpg”,”size”:200436,”sequencer”:”147279EAF9F40933"}}}],”level”:”info”,”msg”:””,”time”:”2016–09–08T15:34:38–07:00"}\n +``` + +## Publish Minio events via Elasticsearch + +Install Elasticsearch 2.4 from [here](https://www.elastic.co/downloads/past-releases/elasticsearch-2-4-0). + +## Recipe steps + +### Step 1: Add Elasticsearch endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the Elasticsearch configuration block in ``config.json`` as follows: + +``` +"elasticsearch": { + "1": { + "enable": true, + "url": "http://127.0.0.1:9200", + "index": "bucketevents" + } + }, +``` +Restart Minio server to reflect config changes. ``bucketevents`` is the index used by Elasticsearch. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded or deleted from ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:elasticsearch``. To understand more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc events add myminio/images arn:minio:sqs:us-east-1:1:elasticsearch --suffix .jpg +mc events list myminio/images +arn:minio:sqs:us-east-1:1:elasticsearch s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” +``` + +### Step 3: Test on Elasticsearch + +Upload a JPEG image into ``images`` bucket, this is the bucket which has been configured for event notification. + +``` +mc cp myphoto.jpg myminio/images +``` + +Run ``curl`` to see new index name ``bucketevents`` in your Elasticsearch setup. + +``` +curl -XGET '127.0.0.1:9200/_cat/indices?v' +health status index pri rep docs.count docs.deleted store.size pri.store.size +yellow open bucketevents 5 1 1 0 7.8kb 7.8kb +``` + +Use curl to view contents of ``bucketevents`` index. + +``` +curl -XGET '127.0.0.1:9200/bucketevents/_search?pretty=1' +{ + "took" : 3, + "timed_out" : false, + "_shards" : { + "total" : 5, + "successful" : 5, + "failed" : 0 + }, + "hits" : { + "total" : 1, + "max_score" : 1.0, + "hits" : [ { + "_index" : "bucketevents", + "_type" : "event", + "_id" : "AVcRVOlwe-uNB1tfj6bx", + "_score" : 1.0, + "_source" : { + "Records" : [ { + "eventVersion" : "2.0", + "eventSource" : "aws:s3", + "awsRegion" : "us-east-1", + "eventTime" : "2016-09-09T23:42:39.977Z", + "eventName" : "s3:ObjectCreated:Put", + "userIdentity" : { + "principalId" : "minio" + }, + "requestParameters" : { + "sourceIPAddress" : "10.1.10.150:52140" + }, + "responseElements" : { }, + "s3" : { + "s3SchemaVersion" : "1.0", + "configurationId" : "Config", + "bucket" : { + "name" : "images", + "ownerIdentity" : { + "principalId" : "minio" + }, + "arn" : "arn:aws:s3:::images" + }, + "object" : { + "key" : "myphoto.jpg", + "size" : 200436, + "sequencer" : "1472CC35E6971AF3" + } + } + } ] + } + } ] + } +} +``` +``curl`` output above states that an Elasticsearch index has been successfully created with notification contents. + + +## Publish Minio events via Redis + +Install Redis from [here](http://redis.io/download). + +## Recipe steps + +### Step 1: Add Redis endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the Redis configuration block in ``config.json`` as follows: + +``` +"redis": { + "1": { + "enable": true, + "address": "127.0.0.1:6379", + "password": "yoursecret", + "key": "bucketevents" + } + } +``` +Restart Minio server to reflect config changes. ``bucketevents`` is the key used by Redis in this example. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded or deleted from ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:redis``. To understand more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc events add myminio/images arn:minio:sqs:us-east-1:1:redis --suffix .jpg +mc events list myminio/images +arn:minio:sqs:us-east-1:1:redis s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” +``` + +### Step 3: Test on Redis + +Redis comes with a handy command line interface ``redis-cli`` to print all notifications on the console. + +``` +redis-cli -a yoursecret +``` + +Open another terminal and upload a JPEG image into ``images`` bucket. + +``` +mc cp myphoto.jpg myminio/images +``` + +``redis-cli`` prints event notification to the console. + +``` +redis-cli -a yoursecret +127.0.0.1:6379> monitor +OK +1474321638.556108 [0 127.0.0.1:40190] "AUTH" "yoursecret" +1474321638.556477 [0 127.0.0.1:40190] "RPUSH" "bucketevents" "{\"Records\":[{\"eventVersion\":\"2.0\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-east-1\",\"eventTime\":\"2016-09-19T21:47:18.555Z\",\"eventName\":\"s3:ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"minio\"},\"requestParameters\":{\"sourceIPAddress\":\"[::1]:39250\"},\"responseElements\":{},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"Config\",\"bucket\":{\"name\":\"images\",\"ownerIdentity\":{\"principalId\":\"minio\"},\"arn\":\"arn:aws:s3:::images\"},\"object\":{\"key\":\"myphoto.jpg\",\"size\":23745,\"sequencer\":\"1475D7B80ECBD853\"}}}],\"level\":\"info\",\"msg\":\"\",\"time\":\"2016-09-19T14:47:18-07:00\"}\n" +``` + +## Publish Minio events via NATS + +Install NATS from [here](http://nats.io/). + +## Recipe steps + +### Step 1: Add NATS endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the NATS configuration block in ``config.json`` as follows: + +``` +"nats": { + "1": { + "enable": true, + "address": "0.0.0.0:4222", + "subject": "bucketevents", + "username": "yourusername", + "password": "yoursecret", + "token": "", + "secure": false, + "pingInterval": 0 + } + }, +``` +Restart Minio server to reflect config changes. ``bucketevents`` is the subject used by NATS in this example. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded or deleted from ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:nats``. To understand more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc events add myminio/images arn:minio:sqs:us-east-1:1:nats --suffix .jpg +mc events list myminio/images +arn:minio:sqs:us-east-1:1:nats s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” +``` + +### Step 3: Test on NATS + +Using this program below we can log the bucket notification added to NATS. + +```go +package main + +// Import Go and NATS packages +import ( + "runtime" + "log" + "github.com/nats-io/nats" +) + +func main() { + + // Create server connection + natsConnection, _ := nats.Connect("nats://yourusername:yoursecret@localhost:4222") + log.Println("Connected") + + // Subscribe to subject + log.Printf("Subscribing to subject 'bucketevents'\n") + natsConnection.Subscribe("bucketevents", func(msg *nats.Msg) { + + // Handle the message + log.Printf("Received message '%s\n", string(msg.Data) + "'") + }) + + // Keep the connection alive + runtime.Goexit() +} +``` + +``` +go run nats.go +2016/10/12 06:39:18 Connected +2016/10/12 06:39:18 Subscribing to subject 'bucketevents' +``` + +Open another terminal and upload a JPEG image into ``images`` bucket. + +``` +mc cp myphoto.jpg myminio/images +``` + +The example ``nats.go`` program prints event notification to console. + +``` +go run nats.go +2016/10/12 06:51:26 Connected +2016/10/12 06:51:26 Subscribing to subject 'bucketevents' +2016/10/12 06:51:33 Received message '{"EventType":"s3:ObjectCreated:Put","Key":"images/myphoto.jpg","Records":[{"eventVersion":"2.0","eventSource":"aws:s3","awsRegion":"us-east-1","eventTime":"2016-10-12T13:51:33Z","eventName":"s3:ObjectCreated:Put","userIdentity":{"principalId":"minio"},"requestParameters":{"sourceIPAddress":"[::1]:57106"},"responseElements":{},"s3":{"s3SchemaVersion":"1.0","configurationId":"Config","bucket":{"name":"images","ownerIdentity":{"principalId":"minio"},"arn":"arn:aws:s3:::images"},"object":{"key":"myphoto.jpg","size":56060,"eTag":"1d97bf45ecb37f7a7b699418070df08f","sequencer":"147CCD1AE054BFD0"}}}],"level":"info","msg":"","time":"2016-10-12T06:51:33-07:00"} +``` + + +## Publish Minio events via PostgreSQL + +Install PostgreSQL from [here](https://www.postgresql.org/). + +## Recipe steps + +### Step 1: Add PostgreSQL endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the PostgreSQL configuration block in ``config.json`` as follows: + +``` +"postgresql": { + "1": { + "enable": true, + "connectionString": "", + "table": "bucketevents", + "host": "127.0.0.1", + "port": "5432", + "user": "postgres", + "password": "mypassword", + "database": "bucketevents_db" + } + } +``` +Restart Minio server to reflect config changes. ``bucketevents`` is the database table used by PostgreSQL in this example. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded or deleted from ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:postgresql``. To understand more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc events add myminio/images arn:minio:sqs:us-east-1:1:postgresql --suffix .jpg +mc events list myminio/images +arn:minio:sqs:us-east-1:1:postgresql s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” +``` + +### Step 3: Test on PostgreSQL + +Open another terminal and upload a JPEG image into ``images`` bucket. + +``` +mc cp myphoto.jpg myminio/images +``` + +Open PostgreSQL terminal to list the saved event notification logs. + +``` +bucketevents_db=# select * from bucketevents; + +key | value +--------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + images/myphoto.jpg | {"Records": [{"s3": {"bucket": {"arn": "arn:aws:s3:::images", "name": "images", "ownerIdentity": {"principalId": "minio"}}, "object": {"key": "myphoto.jpg", "eTag": "1d97bf45ecb37f7a7b699418070df08f", "size": 56060, "sequencer": "147CE57C70B31931"}, "configurationId": "Config", "s3SchemaVersion": "1.0"}, "awsRegion": "us-east-1", "eventName": "s3:ObjectCreated:Put", "eventTime": "2016-10-12T21:18:20Z", "eventSource": "aws:s3", "eventVersion": "2.0", "userIdentity": {"principalId": "minio"}, "responseElements": {}, "requestParameters": {"sourceIPAddress": "[::1]:39706"}}]} +(1 row) +``` + + +## Publish Minio events via kafka + +Install kafka from [here](http://kafka.apache.org/). + +## Recipe steps + +### Step 1: Add kafka endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the kafka configuration block in ``config.json`` as follows: + +``` +"kafka": { + "1": { + "enable": true, + "brokers": ["localhost:9092"], + "topic": "bucketevents" + } +} +``` +Restart Minio server to reflect config changes. ``bucketevents`` is the topic used by kafka in this example. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded or deleted from ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:kafka``. To understand more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc events add myminio/images arn:minio:sqs:us-east-1:1:kafka --suffix .jpg +mc events list myminio/images +arn:minio:sqs:us-east-1:1:kafka s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” +``` + +### Step 3: Test on kafka + +We used [kafkacat](https://github.com/edenhill/kafkacat) to print all notifications on the console. + +``` +kafkacat -b localhost:9092 -t bucketevents +``` + +Open another terminal and upload a JPEG image into ``images`` bucket. + +``` +mc cp myphoto.jpg myminio/images +``` + +``kafkacat`` prints the event notification to the console. + +``` +kafkacat -b localhost:9092 -t bucketevents +{"EventType":"s3:ObjectCreated:Put","Key":"images/myphoto.jpg","Records":[{"eventVersion":"2.0","eventSource":"aws:s3","awsRegion":"us-east-1","eventTime":"2017-01-31T10:01:51Z","eventName":"s3:ObjectCreated:Put","userIdentity":{"principalId":"88QR09S7IOT4X1IBAQ9B"},"requestParameters":{"sourceIPAddress":"192.173.5.2:57904"},"responseElements":{"x-amz-request-id":"149ED2FD25589220","x-minio-origin-endpoint":"http://192.173.5.2:9000"},"s3":{"s3SchemaVersion":"1.0","configurationId":"Config","bucket":{"name":"images","ownerIdentity":{"principalId":"88QR09S7IOT4X1IBAQ9B"},"arn":"arn:aws:s3:::images"},"object":{"key":"myphoto.jpg","size":541596,"eTag":"04451d05b4faf4d62f3d538156115e2a","sequencer":"149ED2FD25589220"}}}],"level":"info","msg":"","time":"2017-01-31T15:31:51+05:30"} +``` +*NOTE* If you are running [distributed Minio](https://docs.minio.io/docs/distributed-minio-quickstart-guide), modify ``~/.minio/config.json`` on all the nodes with your bucket event notification backend configuration. From cd80e6df29c1cfb432af86cc176a51eef683d05f Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 31 Jan 2017 17:17:43 -0800 Subject: [PATCH 32/75] docs: Move the notifications into docs/bucket Cleanup some formatting issues. --- .../notifications}/README.md | 214 +++++++++--------- 1 file changed, 107 insertions(+), 107 deletions(-) rename docs/{bucket-notifications => bucket/notifications}/README.md (80%) diff --git a/docs/bucket-notifications/README.md b/docs/bucket/notifications/README.md similarity index 80% rename from docs/bucket-notifications/README.md rename to docs/bucket/notifications/README.md index 6d3fab028..20539dbad 100644 --- a/docs/bucket-notifications/README.md +++ b/docs/bucket/notifications/README.md @@ -1,50 +1,49 @@ -[![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) +# Minio Bucket Notification Reference Guide [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) -Minio server supports Amazon S3 compatible bucket event notification for the following targets [AMQP](https://www.amqp.org/about/what), [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html) , [Redis](http://redis.io/documentation), [nats.io](http://nats.io/), [PostgreSQL](https://www.postgresql.org) and [kafka](https://kafka.apache.org/). +Minio server supports Amazon S3 compatible bucket event notification for the following targets -## Prerequisites +| Notification Targets| +|:---| +| [`AMQP`](#AMQP) | +| [`Elasticsearch`](#Elasticsearch) | +| [`Redis`](#Redis) | +| [`NATS`](#NATS) | +| [`PostgreSQL`](#PostgreSQL) | +| [`Apache Kafka`](#apache-kafka) | + +## Prerequisites * Install and configure Minio Server from [here](http://docs.minio.io/docs/minio). * Install and configure Minio Client from [here](https://docs.minio.io/docs/minio-client-quickstart-guide). -| Notification Targets| -|:-- -| [`RabbitMQ`](#RabbitMQ) | -| [`Elasticsearch`](#Elasticsearch) | -| [`Redis`](#Redis) | -| [`NATS`](#NATS) | -| [`PostgreSQL`](#PostgreSQL) | -| [`kafka`](#kafka) | - - -## Publish Minio events via RabbitMQ + +## Publish Minio events via AMQP Install RabbitMQ from [here](https://www.rabbitmq.com/). -### Recipe steps +### Step 1: Add AMQP endpoint to Minio -### Step 1: Add RabbitMQ endpoint to Minio +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the AMQP configuration block in ``config.json`` as follows: -The default location of Minio server configuration file is ``~/.minio/config.json``. Update the RabbitMQ configuration block in ``config.json`` as follows: - -``` +```json "amqp": { - "1": { - "enable": true, - "url": "amqp://myuser:mypassword@localhost:5672", - "exchange": "bucketevents", - "routingKey": "bucketlogs", - "exchangeType": "fanout", - "mandatory": false, - "immediate": false, - "durable": false, - "internal": false, - "noWait": false, - "autoDeleted": false - } - } + "1": { + "enable": true, + "url": "amqp://myuser:mypassword@localhost:5672", + "exchange": "bucketevents", + "routingKey": "bucketlogs", + "exchangeType": "fanout", + "mandatory": false, + "immediate": false, + "durable": false, + "internal": false, + "noWait": false, + "autoDeleted": false + } +} ``` -Restart Minio server to reflect config changes. Minio supports all the exchange available in [RabbitMQ](https://www.rabbitmq.com/). For this setup, we are using ``fanout`` exchange. + +Restart Minio server to reflect config changes. Minio supports all the exchanges available in [RabbitMQ](https://www.rabbitmq.com/). For this setup, we are using ``fanout`` exchange. ### Step 2: Enable bucket notification using Minio client @@ -52,14 +51,14 @@ We will enable bucket event notification to trigger whenever a JPEG image is upl ``` mc mb myminio/images -mc events add myminio/images arn:minio:sqs:us-east-1:1:amqp --suffix .jpg +mc events add myminio/images arn:minio:sqs:us-east-1:1:amqp --suffix .jpg mc events list myminio/images arn:minio:sqs:us-east-1:1:amqp s3:ObjectCreated:*,s3:ObjectRemoved:* Filter: suffix=”.jpg” ``` ### Step 3: Test on RabbitMQ -The python program below waits on the queue exchange ``bucketevents`` and prints event notifications on the console. We use [Pika Python Client](https://www.rabbitmq.com/tutorials/tutorial-three-python.html) library to do this. +The python program below waits on the queue exchange ``bucketevents`` and prints event notifications on the console. We use [Pika Python Client](https://www.rabbitmq.com/tutorials/tutorial-three-python.html) library to do this. ```py #!/usr/bin/env python @@ -108,8 +107,9 @@ You should receive the following event notification via RabbitMQ once the upload python rabbit.py ‘{“Records”:[{“eventVersion”:”2.0",”eventSource”:”aws:s3",”awsRegion”:”us-east-1",”eventTime”:”2016–09–08T22:34:38.226Z”,”eventName”:”s3:ObjectCreated:Put”,”userIdentity”:{“principalId”:”minio”},”requestParameters”:{“sourceIPAddress”:”10.1.10.150:44576"},”responseElements”:{},”s3":{“s3SchemaVersion”:”1.0",”configurationId”:”Config”,”bucket”:{“name”:”images”,”ownerIdentity”:{“principalId”:”minio”},”arn”:”arn:aws:s3:::images”},”object”:{“key”:”myphoto.jpg”,”size”:200436,”sequencer”:”147279EAF9F40933"}}}],”level”:”info”,”msg”:””,”time”:”2016–09–08T15:34:38–07:00"}\n ``` + -## Publish Minio events via Elasticsearch +## Publish Minio events via Elasticsearch Install Elasticsearch 2.4 from [here](https://www.elastic.co/downloads/past-releases/elasticsearch-2-4-0). @@ -119,15 +119,16 @@ Install Elasticsearch 2.4 from [here](https://www.elastic.co/downloads/past-rele The default location of Minio server configuration file is ``~/.minio/config.json``. Update the Elasticsearch configuration block in ``config.json`` as follows: -``` +```json "elasticsearch": { - "1": { - "enable": true, - "url": "http://127.0.0.1:9200", - "index": "bucketevents" - } - }, + "1": { + "enable": true, + "url": "http://127.0.0.1:9200", + "index": "bucketevents" + } +}, ``` + Restart Minio server to reflect config changes. ``bucketevents`` is the index used by Elasticsearch. ### Step 2: Enable bucket notification using Minio client @@ -213,6 +214,7 @@ curl -XGET '127.0.0.1:9200/bucketevents/_search?pretty=1' } } ``` + ``curl`` output above states that an Elasticsearch index has been successfully created with notification contents. @@ -220,22 +222,21 @@ curl -XGET '127.0.0.1:9200/bucketevents/_search?pretty=1' Install Redis from [here](http://redis.io/download). -## Recipe steps - ### Step 1: Add Redis endpoint to Minio The default location of Minio server configuration file is ``~/.minio/config.json``. Update the Redis configuration block in ``config.json`` as follows: -``` +```json "redis": { - "1": { - "enable": true, - "address": "127.0.0.1:6379", - "password": "yoursecret", - "key": "bucketevents" - } - } + "1": { + "enable": true, + "address": "127.0.0.1:6379", + "password": "yoursecret", + "key": "bucketevents" + } +} ``` + Restart Minio server to reflect config changes. ``bucketevents`` is the key used by Redis in this example. ### Step 2: Enable bucket notification using Minio client @@ -272,12 +273,11 @@ OK 1474321638.556108 [0 127.0.0.1:40190] "AUTH" "yoursecret" 1474321638.556477 [0 127.0.0.1:40190] "RPUSH" "bucketevents" "{\"Records\":[{\"eventVersion\":\"2.0\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-east-1\",\"eventTime\":\"2016-09-19T21:47:18.555Z\",\"eventName\":\"s3:ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"minio\"},\"requestParameters\":{\"sourceIPAddress\":\"[::1]:39250\"},\"responseElements\":{},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"Config\",\"bucket\":{\"name\":\"images\",\"ownerIdentity\":{\"principalId\":\"minio\"},\"arn\":\"arn:aws:s3:::images\"},\"object\":{\"key\":\"myphoto.jpg\",\"size\":23745,\"sequencer\":\"1475D7B80ECBD853\"}}}],\"level\":\"info\",\"msg\":\"\",\"time\":\"2016-09-19T14:47:18-07:00\"}\n" ``` + -## Publish Minio events via NATS +## Publish Minio events via NATS -Install NATS from [here](http://nats.io/). - -## Recipe steps +Install NATS from [here](http://nats.io/). ### Step 1: Add NATS endpoint to Minio @@ -285,18 +285,19 @@ The default location of Minio server configuration file is ``~/.minio/config.jso ``` "nats": { - "1": { - "enable": true, - "address": "0.0.0.0:4222", - "subject": "bucketevents", - "username": "yourusername", - "password": "yoursecret", - "token": "", - "secure": false, - "pingInterval": 0 - } - }, + "1": { + "enable": true, + "address": "0.0.0.0:4222", + "subject": "bucketevents", + "username": "yourusername", + "password": "yoursecret", + "token": "", + "secure": false, + "pingInterval": 0 + } +}, ``` + Restart Minio server to reflect config changes. ``bucketevents`` is the subject used by NATS in this example. ### Step 2: Enable bucket notification using Minio client @@ -319,27 +320,28 @@ package main // Import Go and NATS packages import ( - "runtime" - "log" - "github.com/nats-io/nats" + "log" + "runtime" + + "github.com/nats-io/nats" ) func main() { - // Create server connection - natsConnection, _ := nats.Connect("nats://yourusername:yoursecret@localhost:4222") - log.Println("Connected") + // Create server connection + natsConnection, _ := nats.Connect("nats://yourusername:yoursecret@localhost:4222") + log.Println("Connected") - // Subscribe to subject - log.Printf("Subscribing to subject 'bucketevents'\n") - natsConnection.Subscribe("bucketevents", func(msg *nats.Msg) { + // Subscribe to subject + log.Printf("Subscribing to subject 'bucketevents'\n") + natsConnection.Subscribe("bucketevents", func(msg *nats.Msg) { - // Handle the message - log.Printf("Received message '%s\n", string(msg.Data) + "'") - }) + // Handle the message + log.Printf("Received message '%s\n", string(msg.Data)+"'") + }) - // Keep the connection alive - runtime.Goexit() + // Keep the connection alive + runtime.Goexit() } ``` @@ -358,7 +360,7 @@ mc cp myphoto.jpg myminio/images The example ``nats.go`` program prints event notification to console. ``` -go run nats.go +go run nats.go 2016/10/12 06:51:26 Connected 2016/10/12 06:51:26 Subscribing to subject 'bucketevents' 2016/10/12 06:51:33 Received message '{"EventType":"s3:ObjectCreated:Put","Key":"images/myphoto.jpg","Records":[{"eventVersion":"2.0","eventSource":"aws:s3","awsRegion":"us-east-1","eventTime":"2016-10-12T13:51:33Z","eventName":"s3:ObjectCreated:Put","userIdentity":{"principalId":"minio"},"requestParameters":{"sourceIPAddress":"[::1]:57106"},"responseElements":{},"s3":{"s3SchemaVersion":"1.0","configurationId":"Config","bucket":{"name":"images","ownerIdentity":{"principalId":"minio"},"arn":"arn:aws:s3:::images"},"object":{"key":"myphoto.jpg","size":56060,"eTag":"1d97bf45ecb37f7a7b699418070df08f","sequencer":"147CCD1AE054BFD0"}}}],"level":"info","msg":"","time":"2016-10-12T06:51:33-07:00"} @@ -369,26 +371,25 @@ go run nats.go Install PostgreSQL from [here](https://www.postgresql.org/). -## Recipe steps - ### Step 1: Add PostgreSQL endpoint to Minio The default location of Minio server configuration file is ``~/.minio/config.json``. Update the PostgreSQL configuration block in ``config.json`` as follows: ``` "postgresql": { - "1": { - "enable": true, - "connectionString": "", - "table": "bucketevents", - "host": "127.0.0.1", - "port": "5432", - "user": "postgres", - "password": "mypassword", - "database": "bucketevents_db" - } - } + "1": { + "enable": true, + "connectionString": "", + "table": "bucketevents", + "host": "127.0.0.1", + "port": "5432", + "user": "postgres", + "password": "mypassword", + "database": "bucketevents_db" + } +} ``` + Restart Minio server to reflect config changes. ``bucketevents`` is the database table used by PostgreSQL in this example. ### Step 2: Enable bucket notification using Minio client @@ -415,32 +416,31 @@ Open PostgreSQL terminal to list the saved event notification logs. ``` bucketevents_db=# select * from bucketevents; -key | value +key | value --------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- images/myphoto.jpg | {"Records": [{"s3": {"bucket": {"arn": "arn:aws:s3:::images", "name": "images", "ownerIdentity": {"principalId": "minio"}}, "object": {"key": "myphoto.jpg", "eTag": "1d97bf45ecb37f7a7b699418070df08f", "size": 56060, "sequencer": "147CE57C70B31931"}, "configurationId": "Config", "s3SchemaVersion": "1.0"}, "awsRegion": "us-east-1", "eventName": "s3:ObjectCreated:Put", "eventTime": "2016-10-12T21:18:20Z", "eventSource": "aws:s3", "eventVersion": "2.0", "userIdentity": {"principalId": "minio"}, "responseElements": {}, "requestParameters": {"sourceIPAddress": "[::1]:39706"}}]} (1 row) -``` +``` - + ## Publish Minio events via kafka Install kafka from [here](http://kafka.apache.org/). -## Recipe steps - ### Step 1: Add kafka endpoint to Minio The default location of Minio server configuration file is ``~/.minio/config.json``. Update the kafka configuration block in ``config.json`` as follows: ``` "kafka": { - "1": { - "enable": true, - "brokers": ["localhost:9092"], - "topic": "bucketevents" - } + "1": { + "enable": true, + "brokers": ["localhost:9092"], + "topic": "bucketevents" + } } ``` + Restart Minio server to reflect config changes. ``bucketevents`` is the topic used by kafka in this example. ### Step 2: Enable bucket notification using Minio client From a9ab01731fb745f9685b9f927c0b7931aa8ca383 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 31 Jan 2017 18:17:31 -0800 Subject: [PATCH 33/75] docs: Remove reference word from notification title --- docs/bucket/notifications/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bucket/notifications/README.md b/docs/bucket/notifications/README.md index 20539dbad..76a74dee2 100644 --- a/docs/bucket/notifications/README.md +++ b/docs/bucket/notifications/README.md @@ -1,4 +1,4 @@ -# Minio Bucket Notification Reference Guide [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) +# Minio Bucket Notification Guide [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) Minio server supports Amazon S3 compatible bucket event notification for the following targets From 35ca3e5d9b9bafcc29e0069281b15442a2518213 Mon Sep 17 00:00:00 2001 From: Karthic Rao Date: Wed, 1 Feb 2017 22:47:32 +0530 Subject: [PATCH 34/75] Fix unresponsiveness of `doneCh` due to Sleep call. (#3667) --- cmd/retry.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cmd/retry.go b/cmd/retry.go index d3ad59e20..79d0b5f4d 100644 --- a/cmd/retry.go +++ b/cmd/retry.go @@ -91,16 +91,26 @@ func newRetryTimer(unit time.Duration, cap time.Duration, jitter float64, doneCh go func() { defer close(attemptCh) nextBackoff := 0 + // Channel used to signal after the expiry of backoff wait seconds. + var timer *time.Timer for { - select { - // Attempts starts. + select { // Attempts starts. case attemptCh <- nextBackoff: nextBackoff++ case <-doneCh: // Stop the routine. return } - time.Sleep(exponentialBackoffWait(nextBackoff)) + timer = time.NewTimer(exponentialBackoffWait(nextBackoff)) + // wait till next backoff time or till doneCh gets a message. + select { + case <-timer.C: + case <-doneCh: + // stop the timer and return. + timer.Stop() + return + } + } }() return attemptCh From 6a6c930f5b13f4416da85cec7e37ea52e77b8245 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 1 Feb 2017 11:16:17 -0800 Subject: [PATCH 35/75] xl: Abort multipart upload should honor quorum properly. (#3670) Current implementation didn't honor quorum properly and didn't handle the errors generated properly. This patch addresses that and also moves common code `cleanupMultipartUploads` into xl specific private function. Fixes #3665 --- cmd/erasure-createfile.go | 4 -- cmd/object-api-multipart-common.go | 40 ---------------- cmd/to_err_test.go | 31 ++++++++++++ cmd/xl-v1-bucket.go | 24 +++------- cmd/xl-v1-healing.go | 12 ++--- cmd/xl-v1-metadata.go | 14 +++--- cmd/xl-v1-multipart.go | 75 +++++++++++++++++++----------- cmd/xl-v1-object.go | 31 ++---------- cmd/xl-v1-utils.go | 17 ------- 9 files changed, 100 insertions(+), 148 deletions(-) create mode 100644 cmd/to_err_test.go diff --git a/cmd/erasure-createfile.go b/cmd/erasure-createfile.go index d20ca8060..f95c0c18c 100644 --- a/cmd/erasure-createfile.go +++ b/cmd/erasure-createfile.go @@ -137,9 +137,5 @@ func appendFile(disks []StorageAPI, volume, path string, enBlocks [][]byte, hash // Wait for all the appends to finish. wg.Wait() - // Do we have write quorum?. - if !isDiskQuorum(wErrs, writeQuorum) { - return traceError(errXLWriteQuorum) - } return reduceWriteQuorumErrs(wErrs, objectOpIgnoredErrs, writeQuorum) } diff --git a/cmd/object-api-multipart-common.go b/cmd/object-api-multipart-common.go index 448cca141..5540e6a43 100644 --- a/cmd/object-api-multipart-common.go +++ b/cmd/object-api-multipart-common.go @@ -22,7 +22,6 @@ import ( "io/ioutil" "path" "sort" - "sync" "time" "github.com/minio/minio/pkg/lock" @@ -161,45 +160,6 @@ func writeUploadJSON(u *uploadsV1, uploadsPath, tmpPath string, disk StorageAPI) return nil } -// Wrapper which removes all the uploaded parts. -func cleanupUploadedParts(bucket, object, uploadID string, storageDisks ...StorageAPI) error { - var errs = make([]error, len(storageDisks)) - var wg = &sync.WaitGroup{} - - // Construct uploadIDPath. - uploadIDPath := path.Join(bucket, object, uploadID) - - // Cleanup uploadID for all disks. - for index, disk := range storageDisks { - if disk == nil { - errs[index] = traceError(errDiskNotFound) - continue - } - wg.Add(1) - // Cleanup each uploadID in a routine. - go func(index int, disk StorageAPI) { - defer wg.Done() - err := cleanupDir(disk, minioMetaMultipartBucket, uploadIDPath) - if err != nil { - errs[index] = err - return - } - errs[index] = nil - }(index, disk) - } - - // Wait for all the cleanups to finish. - wg.Wait() - - // Return first error. - for _, err := range errs { - if err != nil { - return err - } - } - return nil -} - // listMultipartUploadIDs - list all the upload ids from a marker up to 'count'. func listMultipartUploadIDs(bucketName, objectName, uploadIDMarker string, count int, disk StorageAPI) ([]uploadMetadata, bool, error) { var uploads []uploadMetadata diff --git a/cmd/to_err_test.go b/cmd/to_err_test.go new file mode 100644 index 000000000..2311b3619 --- /dev/null +++ b/cmd/to_err_test.go @@ -0,0 +1,31 @@ +/* + * Minio Cloud Storage, (C) 2017 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 cmd + +import "testing" + +func TestToErrIsNil(t *testing.T) { + if toObjectErr(nil) != nil { + t.Errorf("Test expected to return nil, failed instead got a non-nil value %s", toObjectErr(nil)) + } + if toStorageErr(nil) != nil { + t.Errorf("Test expected to return nil, failed instead got a non-nil value %s", toStorageErr(nil)) + } + if toAPIErrorCode(nil) != ErrNone { + t.Errorf("Test expected error code to be ErrNone, failed instead provided %d", toAPIErrorCode(nil)) + } +} diff --git a/cmd/xl-v1-bucket.go b/cmd/xl-v1-bucket.go index 52e993dcf..4078b7292 100644 --- a/cmd/xl-v1-bucket.go +++ b/cmd/xl-v1-bucket.go @@ -62,18 +62,12 @@ func (xl xlObjects) MakeBucket(bucket string) error { // Wait for all make vol to finish. wg.Wait() - // Do we have write quorum?. - if !isDiskQuorum(dErrs, xl.writeQuorum) { + err := reduceWriteQuorumErrs(dErrs, bucketOpIgnoredErrs, xl.writeQuorum) + if errorCause(err) == errXLWriteQuorum { // Purge successfully created buckets if we don't have writeQuorum. undoMakeBucket(xl.storageDisks, bucket) - return toObjectErr(traceError(errXLWriteQuorum), bucket) } - - // Verify we have any other errors which should undo make bucket. - if reducedErr := reduceWriteQuorumErrs(dErrs, bucketOpIgnoredErrs, xl.writeQuorum); reducedErr != nil { - return toObjectErr(reducedErr, bucket) - } - return nil + return toObjectErr(err, bucket) } func (xl xlObjects) undoDeleteBucket(bucket string) { @@ -253,15 +247,9 @@ func (xl xlObjects) DeleteBucket(bucket string) error { // Wait for all the delete vols to finish. wg.Wait() - if !isDiskQuorum(dErrs, xl.writeQuorum) { + err := reduceWriteQuorumErrs(dErrs, bucketOpIgnoredErrs, xl.writeQuorum) + if errorCause(err) == errXLWriteQuorum { xl.undoDeleteBucket(bucket) - return toObjectErr(traceError(errXLWriteQuorum), bucket) } - - if reducedErr := reduceWriteQuorumErrs(dErrs, bucketOpIgnoredErrs, xl.writeQuorum); reducedErr != nil { - return toObjectErr(reducedErr, bucket) - } - - // Success. - return nil + return toObjectErr(err, bucket) } diff --git a/cmd/xl-v1-healing.go b/cmd/xl-v1-healing.go index 1cdb9ce6f..d0aaf56a7 100644 --- a/cmd/xl-v1-healing.go +++ b/cmd/xl-v1-healing.go @@ -109,18 +109,12 @@ func healBucket(storageDisks []StorageAPI, bucket string, writeQuorum int) error // Wait for all make vol to finish. wg.Wait() - // Do we have write quorum?. - if !isDiskQuorum(dErrs, writeQuorum) { + reducedErr := reduceWriteQuorumErrs(dErrs, bucketOpIgnoredErrs, writeQuorum) + if errorCause(reducedErr) == errXLWriteQuorum { // Purge successfully created buckets if we don't have writeQuorum. undoMakeBucket(storageDisks, bucket) - return toObjectErr(traceError(errXLWriteQuorum), bucket) } - - // Verify we have any other errors which should be returned as failure. - if reducedErr := reduceWriteQuorumErrs(dErrs, bucketOpIgnoredErrs, writeQuorum); reducedErr != nil { - return toObjectErr(reducedErr, bucket) - } - return nil + return reducedErr } // Heals all the metadata associated for a given bucket, this function diff --git a/cmd/xl-v1-metadata.go b/cmd/xl-v1-metadata.go index 05149c48e..243dab9fe 100644 --- a/cmd/xl-v1-metadata.go +++ b/cmd/xl-v1-metadata.go @@ -368,13 +368,12 @@ func writeUniqueXLMetadata(disks []StorageAPI, bucket, prefix string, xlMetas [] // Wait for all the routines. wg.Wait() - // Do we have write quorum?. - if !isDiskQuorum(mErrs, quorum) { + err := reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, quorum) + if errorCause(err) == errXLWriteQuorum { // Delete all `xl.json` successfully renamed. deleteAllXLMetadata(disks, bucket, prefix, mErrs) - return traceError(errXLWriteQuorum) } - return reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, quorum) + return err } // writeSameXLMetadata - write `xl.json` on all disks in order. @@ -407,11 +406,10 @@ func writeSameXLMetadata(disks []StorageAPI, bucket, prefix string, xlMeta xlMet // Wait for all the routines. wg.Wait() - // Do we have write Quorum?. - if !isDiskQuorum(mErrs, writeQuorum) { + err := reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, writeQuorum) + if errorCause(err) == errXLWriteQuorum { // Delete all `xl.json` successfully renamed. deleteAllXLMetadata(disks, bucket, prefix, mErrs) - return traceError(errXLWriteQuorum) } - return reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, writeQuorum) + return err } diff --git a/cmd/xl-v1-multipart.go b/cmd/xl-v1-multipart.go index cbaa58f7f..51624784c 100644 --- a/cmd/xl-v1-multipart.go +++ b/cmd/xl-v1-multipart.go @@ -96,8 +96,8 @@ func (xl xlObjects) updateUploadJSON(bucket, object, uploadID string, initiated // Wait for all the writes to finish. wg.Wait() - // Do we have write quorum? - if !isDiskQuorum(errs, xl.writeQuorum) { + err := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum) + if errorCause(err) == errXLWriteQuorum { // No quorum. Perform cleanup on the minority of disks // on which the operation succeeded. @@ -131,7 +131,7 @@ func (xl xlObjects) updateUploadJSON(bucket, object, uploadID string, initiated }(index, disk) } wg.Wait() - return traceError(errXLWriteQuorum) + return err } // we do have quorum, so in case of delete upload.json file @@ -148,11 +148,7 @@ func (xl xlObjects) updateUploadJSON(bucket, object, uploadID string, initiated }(index, disk) } wg.Wait() - - if reducedErr := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum); reducedErr != nil { - return reducedErr - } - return nil + return err } // addUploadID - add upload ID and its initiated time to 'uploads.json'. @@ -266,17 +262,12 @@ func commitXLMetadata(disks []StorageAPI, srcBucket, srcPrefix, dstBucket, dstPr // Wait for all the routines. wg.Wait() - // Do we have write Quorum?. - if !isDiskQuorum(mErrs, quorum) { + err := reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, quorum) + if errorCause(err) == errXLWriteQuorum { // Delete all `xl.json` successfully renamed. deleteAllXLMetadata(disks, dstBucket, dstPrefix, mErrs) - return traceError(errXLWriteQuorum) } - - if reducedErr := reduceWriteQuorumErrs(mErrs, objectOpIgnoredErrs, quorum); reducedErr != nil { - return reducedErr - } - return nil + return err } // listMultipartUploads - lists all multipart uploads. @@ -600,9 +591,10 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Read metadata associated with the object from all disks. partsMetadata, errs = readAllXLMetadata(xl.storageDisks, minioMetaMultipartBucket, uploadIDPath) - if !isDiskQuorum(errs, xl.writeQuorum) { + reducedErr := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum) + if errorCause(reducedErr) == errXLWriteQuorum { preUploadIDLock.RUnlock() - return PartInfo{}, toObjectErr(traceError(errXLWriteQuorum), bucket, object) + return PartInfo{}, toObjectErr(reducedErr, bucket, object) } preUploadIDLock.RUnlock() @@ -720,8 +712,9 @@ func (xl xlObjects) PutObjectPart(bucket, object, uploadID string, partID int, s // Read metadata again because it might be updated with parallel upload of another part. partsMetadata, errs = readAllXLMetadata(onlineDisks, minioMetaMultipartBucket, uploadIDPath) - if !isDiskQuorum(errs, xl.writeQuorum) { - return PartInfo{}, toObjectErr(traceError(errXLWriteQuorum), bucket, object) + reducedErr = reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum) + if errorCause(reducedErr) == errXLWriteQuorum { + return PartInfo{}, toObjectErr(reducedErr, bucket, object) } // Get current highest version based on re-read partsMetadata. @@ -902,9 +895,9 @@ func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, upload // Read metadata associated with the object from all disks. partsMetadata, errs := readAllXLMetadata(xl.storageDisks, minioMetaMultipartBucket, uploadIDPath) - // Do we have writeQuorum?. - if !isDiskQuorum(errs, xl.writeQuorum) { - return ObjectInfo{}, toObjectErr(traceError(errXLWriteQuorum), bucket, object) + reducedErr := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum) + if errorCause(reducedErr) == errXLWriteQuorum { + return ObjectInfo{}, toObjectErr(reducedErr, bucket, object) } onlineDisks, modTime := listOnlineDisks(xl.storageDisks, partsMetadata, errs) @@ -1077,13 +1070,44 @@ func (xl xlObjects) CompleteMultipartUpload(bucket string, object string, upload return objInfo, nil } +// Wrapper which removes all the uploaded parts. +func (xl xlObjects) cleanupUploadedParts(bucket, object, uploadID string) error { + var errs = make([]error, len(xl.storageDisks)) + var wg = &sync.WaitGroup{} + + // Construct uploadIDPath. + uploadIDPath := path.Join(bucket, object, uploadID) + + // Cleanup uploadID for all disks. + for index, disk := range xl.storageDisks { + if disk == nil { + errs[index] = traceError(errDiskNotFound) + continue + } + wg.Add(1) + // Cleanup each uploadID in a routine. + go func(index int, disk StorageAPI) { + defer wg.Done() + err := cleanupDir(disk, minioMetaMultipartBucket, uploadIDPath) + if err != nil { + errs[index] = err + } + }(index, disk) + } + + // Wait for all the cleanups to finish. + wg.Wait() + + return reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, xl.writeQuorum) +} + // abortMultipartUpload - wrapper for purging an ongoing multipart // transaction, deletes uploadID entry from `uploads.json` and purges // the directory at '.minio.sys/multipart/bucket/object/uploadID' holding // all the upload parts. func (xl xlObjects) abortMultipartUpload(bucket, object, uploadID string) (err error) { // Cleanup all uploaded parts. - if err = cleanupUploadedParts(bucket, object, uploadID, xl.storageDisks...); err != nil { + if err = xl.cleanupUploadedParts(bucket, object, uploadID); err != nil { return toObjectErr(err, bucket, object) } @@ -1129,6 +1153,5 @@ func (xl xlObjects) AbortMultipartUpload(bucket, object, uploadID string) error if !xl.isUploadIDExists(bucket, object, uploadID) { return traceError(InvalidUploadID{UploadID: uploadID}) } - err := xl.abortMultipartUpload(bucket, object, uploadID) - return err + return xl.abortMultipartUpload(bucket, object, uploadID) } diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index d25c41d2e..134af0a43 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -34,12 +34,7 @@ import ( ) // list all errors which can be ignored in object operations. -var objectOpIgnoredErrs = []error{ - errDiskNotFound, - errDiskAccessDenied, - errFaultyDisk, - errFaultyRemoteDisk, -} +var objectOpIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied) /// Object Operations @@ -49,11 +44,6 @@ var objectOpIgnoredErrs = []error{ func (xl xlObjects) CopyObject(srcBucket, srcObject, dstBucket, dstObject string, metadata map[string]string) (ObjectInfo, error) { // Read metadata associated with the object from all disks. metaArr, errs := readAllXLMetadata(xl.storageDisks, srcBucket, srcObject) - // Do we have read quorum? - if !isDiskQuorum(errs, xl.readQuorum) { - return ObjectInfo{}, traceError(InsufficientReadQuorum{}, errs...) - } - if reducedErr := reduceReadQuorumErrs(errs, objectOpIgnoredErrs, xl.readQuorum); reducedErr != nil { return ObjectInfo{}, toObjectErr(reducedErr, srcBucket, srcObject) } @@ -159,11 +149,6 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i // Read metadata associated with the object from all disks. metaArr, errs := readAllXLMetadata(xl.storageDisks, bucket, object) - // Do we have read quorum? - if !isDiskQuorum(errs, xl.readQuorum) { - return traceError(InsufficientReadQuorum{}, errs...) - } - if reducedErr := reduceReadQuorumErrs(errs, objectOpIgnoredErrs, xl.readQuorum); reducedErr != nil { return toObjectErr(reducedErr, bucket, object) } @@ -416,12 +401,12 @@ func rename(disks []StorageAPI, srcBucket, srcEntry, dstBucket, dstEntry string, // We can safely allow RenameFile errors up to len(xl.storageDisks) - xl.writeQuorum // otherwise return failure. Cleanup successful renames. - if !isDiskQuorum(errs, quorum) { + err := reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, quorum) + if errorCause(err) == errXLWriteQuorum { // Undo all the partial rename operations. undoRename(disks, srcBucket, srcEntry, dstBucket, dstEntry, isDir, errs) - return traceError(errXLWriteQuorum) } - return reduceWriteQuorumErrs(errs, objectOpIgnoredErrs, quorum) + return err } // renamePart - renames a part of the source object to the destination @@ -751,13 +736,7 @@ func (xl xlObjects) deleteObject(bucket, object string) error { // Wait for all routines to finish. wg.Wait() - // Do we have write quorum? - if !isDiskQuorum(dErrs, xl.writeQuorum) { - // Return errXLWriteQuorum if errors were more than allowed write quorum. - return traceError(errXLWriteQuorum) - } - - return nil + return reduceWriteQuorumErrs(dErrs, objectOpIgnoredErrs, xl.writeQuorum) } // DeleteObject - deletes an object, this call doesn't necessary reply diff --git a/cmd/xl-v1-utils.go b/cmd/xl-v1-utils.go index 4a40fdae7..ecedbad1e 100644 --- a/cmd/xl-v1-utils.go +++ b/cmd/xl-v1-utils.go @@ -83,23 +83,6 @@ func reduceWriteQuorumErrs(errs []error, ignoredErrs []error, writeQuorum int) ( return reduceQuorumErrs(errs, ignoredErrs, writeQuorum, errXLWriteQuorum) } -// List of all errors which are ignored while verifying quorum. -var quorumIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied) - -// Validates if we have quorum based on the errors related to disk only. -// Returns 'true' if we have quorum, 'false' if we don't. -func isDiskQuorum(errs []error, minQuorumCount int) bool { - var count int - errs = errorsCause(errs) - for _, err := range errs { - // Check if the error can be ignored for quorum verification. - if !isErrIgnored(err, quorumIgnoredErrs...) { - count++ - } - } - return count >= minQuorumCount -} - // Similar to 'len(slice)' but returns the actual elements count // skipping the unallocated elements. func diskCount(disks []StorageAPI) int { From 0472e5c1e1fb8f70f93bdcbe8ecc33e70c6d0f0e Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Thu, 2 Feb 2017 00:47:30 +0530 Subject: [PATCH 36/75] Change query param name to duration in list/clear locks API (#3664) Following is a sample list lock API request schematic, /?lock&bucket=mybucket&prefix=myprefix&duration=holdDuration x-minio-operation: list The response would contain the list of locks held on mybucket matching myprefix for a duration longer than holdDuration. --- cmd/admin-handlers.go | 50 +++++++++++++++---------------- cmd/admin-handlers_test.go | 28 ++++++++--------- cmd/admin-rpc-client.go | 22 +++++++------- cmd/admin-rpc-server.go | 8 ++--- cmd/api-errors.go | 2 +- cmd/lockinfo-handlers.go | 9 +++--- cmd/lockinfo-handlers_test.go | 10 +++---- docs/admin-api/README.md | 10 +++---- pkg/madmin/API.md | 8 ++--- pkg/madmin/examples/lock-clear.go | 2 +- pkg/madmin/examples/lock-list.go | 2 +- 11 files changed, 76 insertions(+), 75 deletions(-) diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 5fdfbd47e..d2998c580 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -36,14 +36,14 @@ type mgmtQueryKey string // Only valid query params for list/clear locks management APIs. const ( - mgmtBucket mgmtQueryKey = "bucket" - mgmtObject mgmtQueryKey = "object" - mgmtPrefix mgmtQueryKey = "prefix" - mgmtOlderThan mgmtQueryKey = "older-than" - mgmtDelimiter mgmtQueryKey = "delimiter" - mgmtMarker mgmtQueryKey = "marker" - mgmtMaxKey mgmtQueryKey = "max-key" - mgmtDryRun mgmtQueryKey = "dry-run" + mgmtBucket mgmtQueryKey = "bucket" + mgmtObject mgmtQueryKey = "object" + mgmtPrefix mgmtQueryKey = "prefix" + mgmtLockDuration mgmtQueryKey = "duration" + mgmtDelimiter mgmtQueryKey = "delimiter" + mgmtMarker mgmtQueryKey = "marker" + mgmtMaxKey mgmtQueryKey = "max-key" + mgmtDryRun mgmtQueryKey = "dry-run" ) // ServerVersion - server version @@ -185,7 +185,7 @@ func (adminAPI adminAPIHandlers) ServiceCredentialsHandler(w http.ResponseWriter func validateLockQueryParams(vars url.Values) (string, string, time.Duration, APIErrorCode) { bucket := vars.Get(string(mgmtBucket)) prefix := vars.Get(string(mgmtPrefix)) - relTimeStr := vars.Get(string(mgmtOlderThan)) + durationStr := vars.Get(string(mgmtLockDuration)) // N B empty bucket name is invalid if !IsValidBucketName(bucket) { @@ -198,24 +198,24 @@ func validateLockQueryParams(vars url.Values) (string, string, time.Duration, AP // If older-than parameter was empty then set it to 0s to list // all locks older than now. - if relTimeStr == "" { - relTimeStr = "0s" + if durationStr == "" { + durationStr = "0s" } - relTime, err := time.ParseDuration(relTimeStr) + duration, err := time.ParseDuration(durationStr) if err != nil { errorIf(err, "Failed to parse duration passed as query value.") return "", "", time.Duration(0), ErrInvalidDuration } - return bucket, prefix, relTime, ErrNone + return bucket, prefix, duration, ErrNone } -// ListLocksHandler - GET /?lock&bucket=mybucket&prefix=myprefix&older-than=rel_time +// ListLocksHandler - GET /?lock&bucket=mybucket&prefix=myprefix&duration=duration // - bucket is a mandatory query parameter // - prefix and older-than are optional query parameters // HTTP header x-minio-operation: list // --------- -// Lists locks held on a given bucket, prefix and relative time. +// Lists locks held on a given bucket, prefix and duration it was held for. func (adminAPI adminAPIHandlers) ListLocksHandler(w http.ResponseWriter, r *http.Request) { adminAPIErr := checkRequestAuthType(r, "", "", "") if adminAPIErr != ErrNone { @@ -224,15 +224,15 @@ func (adminAPI adminAPIHandlers) ListLocksHandler(w http.ResponseWriter, r *http } vars := r.URL.Query() - bucket, prefix, relTime, adminAPIErr := validateLockQueryParams(vars) + bucket, prefix, duration, adminAPIErr := validateLockQueryParams(vars) if adminAPIErr != ErrNone { writeErrorResponse(w, adminAPIErr, r.URL) return } // Fetch lock information of locks matching bucket/prefix that - // are available since relTime. - volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, relTime) + // are available for longer than duration. + volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, duration) if err != nil { writeErrorResponse(w, ErrInternalError, r.URL) errorIf(err, "Failed to fetch lock information from remote nodes.") @@ -248,16 +248,16 @@ func (adminAPI adminAPIHandlers) ListLocksHandler(w http.ResponseWriter, r *http } // Reply with list of locks held on bucket, matching prefix - // older than relTime supplied, as json. + // held longer than duration supplied, as json. writeSuccessResponseJSON(w, jsonBytes) } -// ClearLocksHandler - POST /?lock&bucket=mybucket&prefix=myprefix&older-than=relTime +// ClearLocksHandler - POST /?lock&bucket=mybucket&prefix=myprefix&duration=duration // - bucket is a mandatory query parameter // - prefix and older-than are optional query parameters // HTTP header x-minio-operation: clear // --------- -// Clear locks held on a given bucket, prefix and relative time. +// Clear locks held on a given bucket, prefix and duration it was held for. func (adminAPI adminAPIHandlers) ClearLocksHandler(w http.ResponseWriter, r *http.Request) { adminAPIErr := checkRequestAuthType(r, "", "", "") if adminAPIErr != ErrNone { @@ -266,15 +266,15 @@ func (adminAPI adminAPIHandlers) ClearLocksHandler(w http.ResponseWriter, r *htt } vars := r.URL.Query() - bucket, prefix, relTime, adminAPIErr := validateLockQueryParams(vars) + bucket, prefix, duration, adminAPIErr := validateLockQueryParams(vars) if adminAPIErr != ErrNone { writeErrorResponse(w, adminAPIErr, r.URL) return } // Fetch lock information of locks matching bucket/prefix that - // are available since relTime. - volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, relTime) + // are held for longer than duration. + volLocks, err := listPeerLocksInfo(globalAdminPeers, bucket, prefix, duration) if err != nil { writeErrorResponse(w, ErrInternalError, r.URL) errorIf(err, "Failed to fetch lock information from remote nodes.") @@ -289,7 +289,7 @@ func (adminAPI adminAPIHandlers) ClearLocksHandler(w http.ResponseWriter, r *htt return } - // Remove lock matching bucket/prefix older than relTime. + // Remove lock matching bucket/prefix held longer than duration. for _, volLock := range volLocks { globalNSMutex.ForceUnlock(volLock.Bucket, volLock.Object) } diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index dea04ef70..0a8a6c96f 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -334,12 +334,12 @@ func TestServiceSetCreds(t *testing.T) { } // mkLockQueryVal - helper function to build lock query param. -func mkLockQueryVal(bucket, prefix, relTimeStr string) url.Values { +func mkLockQueryVal(bucket, prefix, durationStr string) url.Values { qVal := url.Values{} qVal.Set("lock", "") qVal.Set(string(mgmtBucket), bucket) qVal.Set(string(mgmtPrefix), prefix) - qVal.Set(string(mgmtOlderThan), relTimeStr) + qVal.Set(string(mgmtLockDuration), durationStr) return qVal } @@ -364,41 +364,41 @@ func TestListLocksHandler(t *testing.T) { testCases := []struct { bucket string prefix string - relTime string + duration string expectedStatus int }{ // Test 1 - valid testcase { bucket: "mybucket", prefix: "myobject", - relTime: "1s", + duration: "1s", expectedStatus: http.StatusOK, }, // Test 2 - invalid duration { bucket: "mybucket", prefix: "myprefix", - relTime: "invalidDuration", + duration: "invalidDuration", expectedStatus: http.StatusBadRequest, }, // Test 3 - invalid bucket name { bucket: `invalid\\Bucket`, prefix: "myprefix", - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, // Test 4 - invalid prefix { bucket: "mybucket", prefix: `invalid\\Prefix`, - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, } for i, test := range testCases { - queryVal := mkLockQueryVal(test.bucket, test.prefix, test.relTime) + queryVal := mkLockQueryVal(test.bucket, test.prefix, test.duration) req, err := newTestRequest("GET", "/?"+queryVal.Encode(), 0, nil) if err != nil { t.Fatalf("Test %d - Failed to construct list locks request - %v", i+1, err) @@ -436,41 +436,41 @@ func TestClearLocksHandler(t *testing.T) { testCases := []struct { bucket string prefix string - relTime string + duration string expectedStatus int }{ // Test 1 - valid testcase { bucket: "mybucket", prefix: "myobject", - relTime: "1s", + duration: "1s", expectedStatus: http.StatusOK, }, // Test 2 - invalid duration { bucket: "mybucket", prefix: "myprefix", - relTime: "invalidDuration", + duration: "invalidDuration", expectedStatus: http.StatusBadRequest, }, // Test 3 - invalid bucket name { bucket: `invalid\\Bucket`, prefix: "myprefix", - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, // Test 4 - invalid prefix { bucket: "mybucket", prefix: `invalid\\Prefix`, - relTime: "1h", + duration: "1h", expectedStatus: http.StatusBadRequest, }, } for i, test := range testCases { - queryVal := mkLockQueryVal(test.bucket, test.prefix, test.relTime) + queryVal := mkLockQueryVal(test.bucket, test.prefix, test.duration) req, err := newTestRequest("POST", "/?"+queryVal.Encode(), 0, nil) if err != nil { t.Fatalf("Test %d - Failed to construct clear locks request - %v", i+1, err) diff --git a/cmd/admin-rpc-client.go b/cmd/admin-rpc-client.go index 5f22e6177..b963cbd6a 100644 --- a/cmd/admin-rpc-client.go +++ b/cmd/admin-rpc-client.go @@ -37,7 +37,7 @@ type remoteAdminClient struct { // commands like service stop and service restart. type adminCmdRunner interface { Restart() error - ListLocks(bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) + ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) ReInitDisks() error } @@ -49,8 +49,8 @@ func (lc localAdminClient) Restart() error { } // ListLocks - Fetches lock information from local lock instrumentation. -func (lc localAdminClient) ListLocks(bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) { - return listLocksInfo(bucket, prefix, relTime), nil +func (lc localAdminClient) ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { + return listLocksInfo(bucket, prefix, duration), nil } // Restart - Sends restart command to remote server via RPC. @@ -61,11 +61,11 @@ func (rc remoteAdminClient) Restart() error { } // ListLocks - Sends list locks command to remote server via RPC. -func (rc remoteAdminClient) ListLocks(bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) { +func (rc remoteAdminClient) ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { listArgs := ListLocksQuery{ - bucket: bucket, - prefix: prefix, - relTime: relTime, + bucket: bucket, + prefix: prefix, + duration: duration, } var reply ListLocksReply if err := rc.Call("Admin.ListLocks", &listArgs, &reply); err != nil { @@ -175,8 +175,8 @@ func sendServiceCmd(cps adminPeers, cmd serviceSignal) { } // listPeerLocksInfo - fetch list of locks held on the given bucket, -// matching prefix older than relTime from all peer servers. -func listPeerLocksInfo(peers adminPeers, bucket, prefix string, relTime time.Duration) ([]VolumeLockInfo, error) { +// matching prefix held longer than duration from all peer servers. +func listPeerLocksInfo(peers adminPeers, bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { // Used to aggregate volume lock information from all nodes. allLocks := make([][]VolumeLockInfo, len(peers)) errs := make([]error, len(peers)) @@ -188,11 +188,11 @@ func listPeerLocksInfo(peers adminPeers, bucket, prefix string, relTime time.Dur go func(idx int, remotePeer adminPeer) { defer wg.Done() // `remotePeers` is right-shifted by one position relative to `peers` - allLocks[idx], errs[idx] = remotePeer.cmdRunner.ListLocks(bucket, prefix, relTime) + allLocks[idx], errs[idx] = remotePeer.cmdRunner.ListLocks(bucket, prefix, duration) }(i+1, remotePeer) } wg.Wait() - allLocks[0], errs[0] = localPeer.cmdRunner.ListLocks(bucket, prefix, relTime) + allLocks[0], errs[0] = localPeer.cmdRunner.ListLocks(bucket, prefix, duration) // Summarizing errors received for ListLocks RPC across all // nodes. N B the possible unavailability of quorum in errors diff --git a/cmd/admin-rpc-server.go b/cmd/admin-rpc-server.go index 470082fde..fa5d5e781 100644 --- a/cmd/admin-rpc-server.go +++ b/cmd/admin-rpc-server.go @@ -37,9 +37,9 @@ type adminCmd struct { // ListLocksQuery - wraps ListLocks API's query values to send over RPC. type ListLocksQuery struct { AuthRPCArgs - bucket string - prefix string - relTime time.Duration + bucket string + prefix string + duration time.Duration } // ListLocksReply - wraps ListLocks response over RPC. @@ -63,7 +63,7 @@ func (s *adminCmd) ListLocks(query *ListLocksQuery, reply *ListLocksReply) error if err := query.IsAuthenticated(); err != nil { return err } - volLocks := listLocksInfo(query.bucket, query.prefix, query.relTime) + volLocks := listLocksInfo(query.bucket, query.prefix, query.duration) *reply = ListLocksReply{volLocks: volLocks} return nil } diff --git a/cmd/api-errors.go b/cmd/api-errors.go index ed7529560..6ac5e7f06 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -483,7 +483,7 @@ var errorCodeResponse = map[APIErrorCode]APIError{ }, ErrInvalidDuration: { Code: "InvalidDuration", - Description: "Relative duration provided in the request is invalid.", + Description: "Duration provided in the request is invalid.", HTTPStatusCode: http.StatusBadRequest, }, diff --git a/cmd/lockinfo-handlers.go b/cmd/lockinfo-handlers.go index 9fd98a65f..3a9e093f9 100644 --- a/cmd/lockinfo-handlers.go +++ b/cmd/lockinfo-handlers.go @@ -68,8 +68,8 @@ type OpsLockState struct { Duration time.Duration `json:"duration"` // Duration since the lock was held. } -// listLocksInfo - Fetches locks held on bucket, matching prefix older than relTime. -func listLocksInfo(bucket, prefix string, relTime time.Duration) []VolumeLockInfo { +// listLocksInfo - Fetches locks held on bucket, matching prefix held for longer than duration. +func listLocksInfo(bucket, prefix string, duration time.Duration) []VolumeLockInfo { globalNSMutex.lockMapMutex.Lock() defer globalNSMutex.lockMapMutex.Unlock() @@ -95,11 +95,12 @@ func listLocksInfo(bucket, prefix string, relTime time.Duration) []VolumeLockInf } // Filter locks that are held on bucket, prefix. for opsID, lockInfo := range debugLock.lockInfo { + // filter locks that were held for longer than duration. elapsed := timeNow.Sub(lockInfo.since) - if elapsed < relTime { + if elapsed < duration { continue } - // Add locks that are older than relTime. + // Add locks that are held for longer than duration. volLockInfo.LockDetailsOnObject = append(volLockInfo.LockDetailsOnObject, OpsLockState{ OperationID: opsID, diff --git a/cmd/lockinfo-handlers_test.go b/cmd/lockinfo-handlers_test.go index 78c969151..ebb0f23d5 100644 --- a/cmd/lockinfo-handlers_test.go +++ b/cmd/lockinfo-handlers_test.go @@ -45,34 +45,34 @@ func TestListLocksInfo(t *testing.T) { testCases := []struct { bucket string prefix string - relTime time.Duration + duration time.Duration numLocks int }{ // Test 1 - Matches all the locks acquired above. { bucket: "bucket1", prefix: "prefix1", - relTime: time.Duration(0 * time.Second), + duration: time.Duration(0 * time.Second), numLocks: 20, }, // Test 2 - Bucket doesn't match. { bucket: "bucket", prefix: "prefix1", - relTime: time.Duration(0 * time.Second), + duration: time.Duration(0 * time.Second), numLocks: 0, }, // Test 3 - Prefix doesn't match. { bucket: "bucket1", prefix: "prefix11", - relTime: time.Duration(0 * time.Second), + duration: time.Duration(0 * time.Second), numLocks: 0, }, } for i, test := range testCases { - actual := listLocksInfo(test.bucket, test.prefix, test.relTime) + actual := listLocksInfo(test.bucket, test.prefix, test.duration) if len(actual) != test.numLocks { t.Errorf("Test %d - Expected %d locks but observed %d locks", i+1, test.numLocks, len(actual)) diff --git a/docs/admin-api/README.md b/docs/admin-api/README.md index 90f38b848..c8a045528 100644 --- a/docs/admin-api/README.md +++ b/docs/admin-api/README.md @@ -66,9 +66,9 @@ ### Lock Management APIs * ListLocks - - GET /?lock&bucket=mybucket&prefix=myprefix&older-than=rel_time + - GET /?lock&bucket=mybucket&prefix=myprefix&duration=duration - x-minio-operation: list - - Response: On success 200, json encoded response containing all locks held, older than rel_time. e.g, older than 3 hours. + - Response: On success 200, json encoded response containing all locks held, for longer than duration. - Possible error responses - ErrInvalidBucketName @@ -95,7 +95,7 @@ - ErrInvalidDuration InvalidDuration - Relative duration provided in the request is invalid. + Duration provided in the request is invalid. / @@ -105,9 +105,9 @@ * ClearLocks - - POST /?lock&bucket=mybucket&prefix=myprefix&older-than=rel_time + - POST /?lock&bucket=mybucket&prefix=myprefix&duration=duration - x-minio-operation: clear - - Response: On success 200, json encoded response containing all locks cleared, older than rel_time. e.g, older than 3 hours. + - Response: On success 200, json encoded response containing all locks cleared, for longer than duration. - Possible error responses, similar to errors listed in ListLocks. - ErrInvalidBucketName - ErrInvalidObjectName diff --git a/pkg/madmin/API.md b/pkg/madmin/API.md index 5d588db51..36c79b1a2 100644 --- a/pkg/madmin/API.md +++ b/pkg/madmin/API.md @@ -120,8 +120,8 @@ If successful restarts the running minio service, for distributed setup restarts ``` -### ListLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) -If successful returns information on the list of locks held on ``bucket`` matching ``prefix`` older than ``olderThan`` seconds. +### ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) +If successful returns information on the list of locks held on ``bucket`` matching ``prefix`` for longer than ``duration`` seconds. __Example__ @@ -135,8 +135,8 @@ __Example__ ``` -### ClearLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) -If successful returns information on the list of locks cleared on ``bucket`` matching ``prefix`` older than ``olderThan`` seconds. +### ClearLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) +If successful returns information on the list of locks cleared on ``bucket`` matching ``prefix`` for longer than ``duration`` seconds. __Example__ diff --git a/pkg/madmin/examples/lock-clear.go b/pkg/madmin/examples/lock-clear.go index 2f7a30de4..15fb2bfdf 100644 --- a/pkg/madmin/examples/lock-clear.go +++ b/pkg/madmin/examples/lock-clear.go @@ -37,7 +37,7 @@ func main() { log.Fatalln(err) } - // Clear locks held on mybucket/myprefix older than olderThan seconds. + // Clear locks held on mybucket/myprefix for longer than 30s. olderThan := time.Duration(30 * time.Second) locksCleared, err := madmClnt.ClearLocks("mybucket", "myprefix", olderThan) if err != nil { diff --git a/pkg/madmin/examples/lock-list.go b/pkg/madmin/examples/lock-list.go index bc1e9ff08..88023f4b4 100644 --- a/pkg/madmin/examples/lock-list.go +++ b/pkg/madmin/examples/lock-list.go @@ -37,7 +37,7 @@ func main() { log.Fatalln(err) } - // List locks held on mybucket/myprefix older than 30s. + // List locks held on mybucket/myprefix for longer than 30s. locksHeld, err := madmClnt.ListLocks("mybucket", "myprefix", time.Duration(30*time.Second)) if err != nil { log.Fatalln(err) From f612a7dd8574ed98ac30ca0f3758f49fa5369635 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 1 Feb 2017 20:46:49 +0100 Subject: [PATCH 37/75] madmin: Fix a typo in Locks duration query name (#3673) --- pkg/madmin/lock-commands.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/madmin/lock-commands.go b/pkg/madmin/lock-commands.go index 7285a82d5..3a3b44f56 100644 --- a/pkg/madmin/lock-commands.go +++ b/pkg/madmin/lock-commands.go @@ -93,12 +93,12 @@ func getLockInfos(body io.Reader) ([]VolumeLockInfo, error) { // ListLocks - Calls List Locks Management API to fetch locks matching // bucket, prefix and held before the duration supplied. -func (adm *AdminClient) ListLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) { +func (adm *AdminClient) ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { queryVal := make(url.Values) queryVal.Set("lock", "") queryVal.Set("bucket", bucket) queryVal.Set("prefix", prefix) - queryVal.Set("older-than", olderThan.String()) + queryVal.Set("duration", duration.String()) hdrs := make(http.Header) hdrs.Set(minioAdminOpHeader, "list") @@ -125,12 +125,12 @@ func (adm *AdminClient) ListLocks(bucket, prefix string, olderThan time.Duration // ClearLocks - Calls Clear Locks Management API to clear locks held // on bucket, matching prefix older than duration supplied. -func (adm *AdminClient) ClearLocks(bucket, prefix string, olderThan time.Duration) ([]VolumeLockInfo, error) { +func (adm *AdminClient) ClearLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) { queryVal := make(url.Values) queryVal.Set("lock", "") queryVal.Set("bucket", bucket) queryVal.Set("prefix", prefix) - queryVal.Set("older-than", olderThan.String()) + queryVal.Set("duration", duration.String()) hdrs := make(http.Header) hdrs.Set(minioAdminOpHeader, "clear") From fc446e0b812eb1c6c56a413a3c77e818227394bd Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 1 Feb 2017 13:12:13 -0800 Subject: [PATCH 38/75] docs: Add browser doc for running dev in custom port (#3675) Fixes #3674 --- browser/README.md | 57 +++++++++++++++++++++++++++++++-------- browser/webpack.config.js | 3 ++- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/browser/README.md b/browser/README.md index 74bb563f2..647147fdf 100644 --- a/browser/README.md +++ b/browser/README.md @@ -4,34 +4,69 @@ ## Installation -### Install yarn: +### Install yarn ```sh -$ curl -o- -L https://yarnpkg.com/install.sh | bash -$ yarn +curl -o- -L https://yarnpkg.com/install.sh | bash +yarn ``` -### Install `go-bindata` and `go-bindata-assetfs`. +### Install `go-bindata` and `go-bindata-assetfs` If you do not have a working Golang environment, please follow [Install Golang](https://docs.minio.io/docs/how-to-install-golang) ```sh -$ go get github.com/jteeuwen/go-bindata/... -$ go get github.com/elazarl/go-bindata-assetfs/... +go get github.com/jteeuwen/go-bindata/... +go get github.com/elazarl/go-bindata-assetfs/... ``` -## Generating Assets. +## Generating Assets ### Generate ui-assets.go ```sh -$ yarn release +yarn release ``` -This generates ui-assets.go in the current direcotry. Now do `make` in the parent directory to build the minio binary with the newly generated ui-assets.go -### Run Minio Browser with live reload. +This generates ui-assets.go in the current direcotry. Now do `make` in the parent directory to build the minio binary with the newly generated ``ui-assets.go`` + +### Run Minio Browser with live reload ```sh -$ yarn dev +yarn dev ``` Open [http://localhost:8080/minio/](http://localhost:8080/minio/) in your browser to play with the application + +### Run Minio Browser with live reload on custom port + +Edit `browser/webpack.config.js` + +```diff +diff --git a/browser/webpack.config.js b/browser/webpack.config.js +index 3ccdaba..9496c56 100644 +--- a/browser/webpack.config.js ++++ b/browser/webpack.config.js +@@ -58,6 +58,7 @@ var exports = { + historyApiFallback: { + index: '/minio/' + }, ++ port: 8888, + proxy: { + '/minio/webrpc': { + target: 'http://localhost:9000', +@@ -97,7 +98,7 @@ var exports = { + if (process.env.NODE_ENV === 'dev') { + exports.entry = [ + 'webpack/hot/dev-server', +- 'webpack-dev-server/client?http://localhost:8080', ++ 'webpack-dev-server/client?http://localhost:8888', + path.resolve(__dirname, 'app/index.js') + ] + } +``` + +```sh +yarn dev +``` + +Open [http://localhost:8888/minio/](http://localhost:8888/minio/) in your browser to play with the application diff --git a/browser/webpack.config.js b/browser/webpack.config.js index 3ccdaba0b..9496c56ef 100644 --- a/browser/webpack.config.js +++ b/browser/webpack.config.js @@ -58,6 +58,7 @@ var exports = { historyApiFallback: { index: '/minio/' }, + port: 8888, proxy: { '/minio/webrpc': { target: 'http://localhost:9000', @@ -97,7 +98,7 @@ var exports = { if (process.env.NODE_ENV === 'dev') { exports.entry = [ 'webpack/hot/dev-server', - 'webpack-dev-server/client?http://localhost:8080', + 'webpack-dev-server/client?http://localhost:8888', path.resolve(__dirname, 'app/index.js') ] } From 4b4cb07fb6b882f6c244d7f89c566e6a3c318449 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 2 Feb 2017 03:01:49 -0800 Subject: [PATCH 39/75] Update browser assets with new changes. --- browser/ui-assets.go | 50 +++++++++++++++++++-------------------- browser/webpack.config.js | 3 +-- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/browser/ui-assets.go b/browser/ui-assets.go index b8c898e5a..2405f86b9 100644 --- a/browser/ui-assets.go +++ b/browser/ui-assets.go @@ -4,7 +4,7 @@ // production/favicon.ico // production/firefox.png // production/index.html -// production/index_bundle-2017-01-31T00-38-09Z.js +// production/index_bundle-2017-02-02T11-00-00Z.js // production/loader.css // production/logo.svg // production/safari.png @@ -65,7 +65,7 @@ func productionChromePng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -82,7 +82,7 @@ func productionFaviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -99,7 +99,7 @@ func productionFirefoxPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -156,8 +156,8 @@ var _productionIndexHTML = []byte(`
    - - + + `) @@ -172,12 +172,12 @@ func productionIndexHTML() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _productionIndex_bundle20170131t003809zJs = []byte(`!function(A){function M(I){if(t[I])return t[I].exports;var g=t[I]={exports:{},id:I,loaded:!1};return A[I].call(g.exports,g,g.exports,M),g.loaded=!0,g.exports}var t={};return M.m=A,M.c=t,M.p="",M(0)}([function(A,M,t){A.exports=t(240)},function(A,M,t){"use strict";A.exports=t(439)},function(A,M,t){"use strict";function I(A,M,t,I,g,e,i,T){if(!A){var E;if(void 0===M)E=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var N=[t,I,g,e,i,T],o=0;E=new Error(M.replace(/%s/g,function(){return N[o++]})),E.name="Invariant Violation"}throw E.framesToPop=1,E}}A.exports=I},function(A,M,t){"use strict";var I=t(20),g=I;A.exports=g},function(A,M){"use strict";function t(A,M){if(null==A)throw new TypeError("Object.assign target cannot be null or undefined");for(var t=Object(A),I=Object.prototype.hasOwnProperty,g=1;gM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;iM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;i-1&&A%1==0&&A1)for(var t=1;tA.clientHeight}Object.defineProperty(M,"__esModule",{value:!0}),M.default=i;var T=t(57),E=I(T),N=t(39),o=I(N);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):"function"!==E&&"string"!==E?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):null}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M){"use strict";function t(A){function M(M,t,I,g,e,i){var T=g||"<>",E=i||I;if(null==t[I])return M?new Error("Required "+e+" ` + "`" + `"+E+"` + "`" + ` was not specified "+("in ` + "`" + `"+T+"` + "`" + `.")):null;for(var N=arguments.length,o=Array(N>6?N-6:0),n=6;n=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return 0===A.button}function i(A){return!!(A.metaKey||A.altKey||A.ctrlKey||A.shiftKey)}function T(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!1;return!0}function E(A,M){var t=M.query,I=M.hash,g=M.state;return t||I||g?{pathname:A,query:t,hash:I,state:g}:A}M.__esModule=!0;var N=Object.assign||function(A){for(var M=1;M=0;I--){var g=A[I],e=g.path||"";if(t=e.replace(/\/*$/,"/")+t,0===e.indexOf("/"))break}return"/"+t}},propTypes:{path:C,from:C,to:C.isRequired,query:c,state:c,onEnter:o.falsy,children:o.falsy},render:function(){(0,T.default)(!1)}});M.default=D,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0;var g=t(1),e=I(g),i=t(8),T=I(i),E=t(30),N=t(34),o=e.default.PropTypes,n=o.string,C=o.func,c=e.default.createClass({displayName:"Route",statics:{createRouteFromReactElement:E.createRouteFromReactElement},propTypes:{path:n,component:N.component,components:N.components,getComponent:C,getComponents:C},render:function(){(0,T.default)(!1)}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return!A||!A.__v2_compatible__}function i(A){return A&&A.getCurrentLocation}M.__esModule=!0;var T=Object.assign||function(A){for(var M=1;M=0&&0===window.sessionStorage.length)return;throw A}}function i(A){var M=void 0;try{M=window.sessionStorage.getItem(g(A))}catch(A){if(A.name===o)return null}if(M)try{return JSON.parse(M)}catch(A){}return null}M.__esModule=!0,M.saveState=e,M.readState=i;var T=t(23),E=(I(T),"@@History/"),N=["QuotaExceededError","QUOTA_EXCEEDED_ERR"],o="SecurityError"},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){function M(A){return E.canUseDOM?void 0:T.default(!1),t.listen(A)}var t=n.default(e({getUserConfirmation:N.getUserConfirmation},A,{go:N.go}));return e({},t,{listen:M})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M1?M-1:0),e=1;e=A.childNodes.length?null:A.childNodes.item(t);A.insertBefore(M,I)}var g=t(433),e=t(220),i=t(17),T=t(76),E=t(121),N=t(2),o={dangerouslyReplaceNodeWithMarkup:g.dangerouslyReplaceNodeWithMarkup,updateTextContent:E,processUpdates:function(A,M){for(var t,i=null,o=null,n=0;n-1?void 0:i(!1),!N.plugins[t]){M.extractEvents?void 0:i(!1),N.plugins[t]=M;var I=M.eventTypes;for(var e in I)g(I[e],M,e)?void 0:i(!1)}}}function g(A,M,t){N.eventNameDispatchConfigs.hasOwnProperty(t)?i(!1):void 0,N.eventNameDispatchConfigs[t]=A;var I=A.phasedRegistrationNames;if(I){for(var g in I)if(I.hasOwnProperty(g)){var T=I[g];e(T,M,t)}return!0}return!!A.registrationName&&(e(A.registrationName,M,t),!0)}function e(A,M,t){N.registrationNameModules[A]?i(!1):void 0,N.registrationNameModules[A]=M,N.registrationNameDependencies[A]=M.eventTypes[t].dependencies}var i=t(2),T=null,E={},N={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(A){T?i(!1):void 0,T=Array.prototype.slice.call(A),I()},injectEventPluginsByName:function(A){var M=!1;for(var t in A)if(A.hasOwnProperty(t)){var g=A[t];E.hasOwnProperty(t)&&E[t]===g||(E[t]?i(!1):void 0,E[t]=g,M=!0)}M&&I()},getPluginModuleForEvent:function(A){var M=A.dispatchConfig;if(M.registrationName)return N.registrationNameModules[M.registrationName]||null;for(var t in M.phasedRegistrationNames)if(M.phasedRegistrationNames.hasOwnProperty(t)){var I=N.registrationNameModules[M.phasedRegistrationNames[t]];if(I)return I}return null},_resetEventPlugins:function(){T=null;for(var A in E)E.hasOwnProperty(A)&&delete E[A];N.plugins.length=0;var M=N.eventNameDispatchConfigs;for(var t in M)M.hasOwnProperty(t)&&delete M[t];var I=N.registrationNameModules;for(var g in I)I.hasOwnProperty(g)&&delete I[g]}};A.exports=N},function(A,M,t){"use strict";function I(A){return(""+A).replace(x,"//")}function g(A,M){this.func=A,this.context=M,this.count=0}function e(A,M,t){var I=A.func,g=A.context;I.call(g,M,A.count++)}function i(A,M,t){if(null==A)return A;var I=g.getPooled(M,t);Q(A,e,I),g.release(I)}function T(A,M,t,I){this.result=A,this.keyPrefix=M,this.func=t,this.context=I,this.count=0}function E(A,M,t){var g=A.result,e=A.keyPrefix,i=A.func,T=A.context,E=i.call(T,M,A.count++);Array.isArray(E)?N(E,g,t,B.thatReturnsArgument):null!=E&&(a.isValidElement(E)&&(E=a.cloneAndReplaceKey(E,e+(E!==M?I(E.key||"")+"/":"")+t)),g.push(E))}function N(A,M,t,g,e){var i="";null!=t&&(i=I(t)+"/");var N=T.getPooled(M,i,g,e);Q(A,E,N),T.release(N)}function o(A,M,t){if(null==A)return A;var I=[];return N(A,I,null,M,t),I}function n(A,M,t){return null}function C(A,M){return Q(A,n,null)}function c(A){var M=[];return N(A,M,null,B.thatReturnsArgument),M}var D=t(31),a=t(13),B=t(20),Q=t(123),r=D.twoArgumentPooler,s=D.fourArgumentPooler,x=/\/(?!\/)/g;g.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},D.addPoolingTo(g,r),T.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},D.addPoolingTo(T,s);var j={forEach:i,map:o,mapIntoWithKeyPrefixInternal:N,count:C,toArray:c};A.exports=j},function(A,M,t){"use strict";function I(A,M){var t=y.hasOwnProperty(M)?y[M]:null;w.hasOwnProperty(M)&&(t!==x.OVERRIDE_BASE?B(!1):void 0),A.hasOwnProperty(M)&&(t!==x.DEFINE_MANY&&t!==x.DEFINE_MANY_MERGED?B(!1):void 0)}function g(A,M){if(M){"function"==typeof M?B(!1):void 0,C.isValidElement(M)?B(!1):void 0;var t=A.prototype;M.hasOwnProperty(s)&&u.mixins(A,M.mixins);for(var g in M)if(M.hasOwnProperty(g)&&g!==s){var e=M[g];if(I(t,g),u.hasOwnProperty(g))u[g](A,e);else{var i=y.hasOwnProperty(g),N=t.hasOwnProperty(g),o="function"==typeof e,n=o&&!i&&!N&&M.autobind!==!1;if(n)t.__reactAutoBindMap||(t.__reactAutoBindMap={}),t.__reactAutoBindMap[g]=e,t[g]=e;else if(N){var c=y[g];!i||c!==x.DEFINE_MANY_MERGED&&c!==x.DEFINE_MANY?B(!1):void 0,c===x.DEFINE_MANY_MERGED?t[g]=T(t[g],e):c===x.DEFINE_MANY&&(t[g]=E(t[g],e))}else t[g]=e}}}}function e(A,M){if(M)for(var t in M){var I=M[t];if(M.hasOwnProperty(t)){var g=t in u;g?B(!1):void 0;var e=t in A;e?B(!1):void 0,A[t]=I}}}function i(A,M){A&&M&&"object"==typeof A&&"object"==typeof M?void 0:B(!1);for(var t in M)M.hasOwnProperty(t)&&(void 0!==A[t]?B(!1):void 0,A[t]=M[t]);return A}function T(A,M){return function(){var t=A.apply(this,arguments),I=M.apply(this,arguments);if(null==t)return I;if(null==I)return t;var g={};return i(g,t),i(g,I),g}}function E(A,M){return function(){A.apply(this,arguments),M.apply(this,arguments)}}function N(A,M){var t=M.bind(A);return t}function o(A){for(var M in A.__reactAutoBindMap)if(A.__reactAutoBindMap.hasOwnProperty(M)){var t=A.__reactAutoBindMap[M];A[M]=N(A,t)}}var n=t(207),C=t(13),c=(t(71),t(70),t(222)),D=t(4),a=t(50),B=t(2),Q=t(59),r=t(27),s=(t(3),r({mixins:null})),x=Q({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),j=[],y={mixins:x.DEFINE_MANY,statics:x.DEFINE_MANY,propTypes:x.DEFINE_MANY,contextTypes:x.DEFINE_MANY,childContextTypes:x.DEFINE_MANY,getDefaultProps:x.DEFINE_MANY_MERGED,getInitialState:x.DEFINE_MANY_MERGED,getChildContext:x.DEFINE_MANY_MERGED,render:x.DEFINE_ONCE,componentWillMount:x.DEFINE_MANY,componentDidMount:x.DEFINE_MANY,componentWillReceiveProps:x.DEFINE_MANY,shouldComponentUpdate:x.DEFINE_ONCE,componentWillUpdate:x.DEFINE_MANY,componentDidUpdate:x.DEFINE_MANY,componentWillUnmount:x.DEFINE_MANY,updateComponent:x.OVERRIDE_BASE},u={displayName:function(A,M){A.displayName=M},mixins:function(A,M){if(M)for(var t=0;t"+T+""},receiveComponent:function(A,M){if(A!==this._currentElement){this._currentElement=A;var t=""+A;if(t!==this._stringText){this._stringText=t;var g=i.getNode(this._rootNodeID);I.updateTextContent(g,t)}}},unmountComponent:function(){e.unmountIDFromEnvironment(this._rootNodeID)}}),A.exports=o},function(A,M,t){"use strict";function I(){this.reinitializeTransaction()}var g=t(18),e=t(73),i=t(4),T=t(20),E={initialize:T,close:function(){C.isBatchingUpdates=!1}},N={initialize:T,close:g.flushBatchedUpdates.bind(g)},o=[N,E];i(I.prototype,e.Mixin,{getTransactionWrappers:function(){return o}});var n=new I,C={isBatchingUpdates:!1,batchedUpdates:function(A,M,t,I,g,e){var i=C.isBatchingUpdates;C.isBatchingUpdates=!0,i?A(M,t,I,g,e):n.perform(A,null,M,t,I,g,e)}};A.exports=C},function(A,M,t){"use strict";function I(){if(!L){L=!0,Q.EventEmitter.injectReactEventListener(B),Q.EventPluginHub.injectEventPluginOrder(T),Q.EventPluginHub.injectInstanceHandle(r),Q.EventPluginHub.injectMount(s),Q.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:u,EnterLeaveEventPlugin:E,ChangeEventPlugin:e,SelectEventPlugin:j,BeforeInputEventPlugin:g}),Q.NativeComponent.injectGenericComponentClass(D),Q.NativeComponent.injectTextComponentClass(a),Q.Class.injectMixin(n),Q.DOMProperty.injectDOMPropertyConfig(o),Q.DOMProperty.injectDOMPropertyConfig(w),Q.EmptyComponent.injectEmptyComponent("noscript"),Q.Updates.injectReconcileTransaction(x),Q.Updates.injectBatchingStrategy(c),Q.RootIndex.injectCreateReactRootIndex(N.canUseDOM?i.createReactRootIndex:y.createReactRootIndex),Q.Component.injectEnvironment(C)}}var g=t(429),e=t(431),i=t(432),T=t(434),E=t(435),N=t(10),o=t(438),n=t(440),C=t(109),c=t(212),D=t(444),a=t(211),B=t(452),Q=t(453),r=t(48),s=t(12),x=t(457),j=t(463),y=t(464),u=t(465),w=t(462),L=!1;A.exports={inject:I}},function(A,M,t){"use strict";function I(){if(n.current){var A=n.current.getName();if(A)return" Check the render method of ` + "`" + `"+A+"` + "`" + `."}return""}function g(A,M){if(A._store&&!A._store.validated&&null==A.key){A._store.validated=!0;e("uniqueKey",A,M)}}function e(A,M,t){var g=I();if(!g){var e="string"==typeof t?t:t.displayName||t.name;e&&(g=" Check the top-level render call using <"+e+">.")}var i=D[A]||(D[A]={});if(i[g])return null;i[g]=!0;var T={parentOrOwner:g,url:" See https://fb.me/react-warning-keys for more information.",childOwner:null};return M&&M._owner&&M._owner!==n.current&&(T.childOwner=" It was passed a child from "+M._owner.getName()+"."),T}function i(A,M){if("object"==typeof A)if(Array.isArray(A))for(var t=0;t/,e={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(A){var M=I(A);return A.replace(g," "+e.CHECKSUM_ATTR_NAME+'="'+M+'"$&')},canReuseMarkup:function(A,M){var t=M.getAttribute(e.CHECKSUM_ATTR_NAME);t=t&&parseInt(t,10);var g=I(A);return g===t}};A.exports=e},function(A,M,t){"use strict";var I=t(59),g=I({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOVE_NODE:null,SET_MARKUP:null,TEXT_CONTENT:null});A.exports=g},function(A,M,t){"use strict";function I(A){if("function"==typeof A.type)return A.type;var M=A.type,t=n[M];return null==t&&(n[M]=t=N(M)),t}function g(A){return o?void 0:E(!1),new o(A.type,A.props)}function e(A){return new C(A)}function i(A){return A instanceof C}var T=t(4),E=t(2),N=null,o=null,n={},C=null,c={injectGenericComponentClass:function(A){o=A},injectTextComponentClass:function(A){C=A},injectComponentClasses:function(A){T(n,A)}},D={getComponentClassForElement:I,createInternalComponent:g,createInstanceForText:e,isTextComponent:i,injection:c};A.exports=D},function(A,M,t){"use strict";function I(A,M){}var g=(t(3),{isMounted:function(A){return!1},enqueueCallback:function(A,M){},enqueueForceUpdate:function(A){I(A,"forceUpdate")},enqueueReplaceState:function(A,M){I(A,"replaceState")},enqueueSetState:function(A,M){I(A,"setState")},enqueueSetProps:function(A,M){I(A,"setProps")},enqueueReplaceProps:function(A,M){I(A,"replaceProps")}});A.exports=g},function(A,M,t){"use strict";function I(A){function M(M,t,I,g,e,i){if(g=g||y,i=i||I,null==t[I]){var T=s[e];return M?new Error("Required "+T+" ` + "`" + `"+i+"` + "`" + ` was not specified in "+("` + "`" + `"+g+"` + "`" + `.")):null}return A(t,I,g,e,i)}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}function g(A){function M(M,t,I,g,e){var i=M[t],T=a(i);if(T!==A){var E=s[g],N=B(i);return new Error("Invalid "+E+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+N+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected ")+("` + "`" + `"+A+"` + "`" + `."))}return null}return I(M)}function e(){return I(x.thatReturns(null))}function i(A){function M(M,t,I,g,e){var i=M[t];if(!Array.isArray(i)){var T=s[g],E=a(i);return new Error("Invalid "+T+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+E+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected an array."))}for(var N=0;N>"}var r=t(13),s=t(70),x=t(20),j=t(118),y="<>",u={array:g("array"),bool:g("boolean"),func:g("function"),number:g("number"),object:g("object"),string:g("string"),any:e(),arrayOf:i,element:T(),instanceOf:E,node:C(),objectOf:o,oneOf:N,oneOfType:n,shape:c};A.exports=u},function(A,M){"use strict";var t={injectCreateReactRootIndex:function(A){I.createReactRootIndex=A}},I={createReactRootIndex:null,injection:t};A.exports=I},function(A,M){"use strict";var t={currentScrollLeft:0,currentScrollTop:0,refreshScrollValues:function(A){t.currentScrollLeft=A.x,t.currentScrollTop=A.y}};A.exports=t},function(A,M,t){"use strict";function I(A,M){if(null==M?g(!1):void 0,null==A)return M;var t=Array.isArray(A),I=Array.isArray(M);return t&&I?(A.push.apply(A,M),A):t?(A.push(M),A):I?[A].concat(M):[A,M]}var g=t(2);A.exports=I},function(A,M){"use strict";var t=function(A,M,t){Array.isArray(A)?A.forEach(M,t):A&&M.call(t,A)};A.exports=t},function(A,M,t){"use strict";function I(){return!e&&g.canUseDOM&&(e="textContent"in document.documentElement?"textContent":"innerText"),e}var g=t(10),e=null;A.exports=I},function(A,M){"use strict";function t(A){var M=A&&A.nodeName&&A.nodeName.toLowerCase();return M&&("input"===M&&I[A.type]||"textarea"===M)}var I={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};A.exports=t},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(){for(var A=arguments.length,M=Array(A),t=0;t=0&&s.splice(M,1)}function T(A){var M=document.createElement("style");return M.type="text/css",e(A,M),M}function E(A){var M=document.createElement("link");return M.rel="stylesheet",e(A,M),M}function N(A,M){var t,I,g;if(M.singleton){var e=r++;t=Q||(Q=T(M)),I=o.bind(null,t,e,!1),g=o.bind(null,t,e,!0)}else A.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(t=E(M),I=C.bind(null,t),g=function(){i(t),t.href&&URL.revokeObjectURL(t.href)}):(t=T(M),I=n.bind(null,t),g=function(){i(t)});return I(A),function(M){if(M){if(M.css===A.css&&M.media===A.media&&M.sourceMap===A.sourceMap)return;I(A=M)}else g()}}function o(A,M,t,I){var g=t?"":I.css;if(A.styleSheet)A.styleSheet.cssText=x(M,g);else{var e=document.createTextNode(g),i=A.childNodes;i[M]&&A.removeChild(i[M]),i.length?A.insertBefore(e,i[M]):A.appendChild(e)}}function n(A,M){var t=M.css,I=M.media;if(I&&A.setAttribute("media",I),A.styleSheet)A.styleSheet.cssText=t;else{for(;A.firstChild;)A.removeChild(A.firstChild);A.appendChild(document.createTextNode(t))}}function C(A,M){var t=M.css,I=M.sourceMap;I&&(t+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(I))))+" */");var g=new Blob([t],{type:"text/css"}),e=A.href;A.href=URL.createObjectURL(g),e&&URL.revokeObjectURL(e)}var c={},D=function(A){var M;return function(){return"undefined"==typeof M&&(M=A.apply(this,arguments)),M}},a=D(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),B=D(function(){return document.head||document.getElementsByTagName("head")[0]}),Q=null,r=0,s=[];A.exports=function(A,M){M=M||{},"undefined"==typeof M.singleton&&(M.singleton=a()),"undefined"==typeof M.insertAt&&(M.insertAt="bottom");var t=g(A);return I(t,M),function(A){for(var e=[],i=0;i",'"',"` + "`" + `"," ","\r","\n","\t"],D=["{","}","|","\\","^","` + "`" + `"].concat(c),a=["'"].concat(D),B=["%","/","?",";","#"].concat(a),Q=["/","?","#"],r=255,s=/^[+a-z0-9A-Z_-]{0,63}$/,x=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,j={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},u={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=t(360);I.prototype.parse=function(A,M,t){if(!N.isString(A))throw new TypeError("Parameter 'url' must be a string, not "+typeof A);var I=A.indexOf("?"),g=I!==-1&&I127?"x":O[F];if(!m.match(s)){var k=U.slice(0,Y),R=U.slice(Y+1),J=O.match(x);J&&(k.push(J[1]),R.unshift(J[2])),R.length&&(T="/"+R.join(".")+T),this.hostname=k.join(".");break}}}this.hostname.length>r?this.hostname="":this.hostname=this.hostname.toLowerCase(),z||(this.hostname=E.toASCII(this.hostname));var G=this.port?":"+this.port:"",H=this.hostname||"";this.host=H+G,this.href+=this.host,z&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==T[0]&&(T="/"+T))}if(!j[D])for(var Y=0,p=a.length;Y0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return t.search=A.search,t.query=A.query,N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!j.length)return t.pathname=null,t.search?t.path="/"+t.search:t.path=null,t.href=t.format(),t;for(var l=j.slice(-1)[0],Y=(t.host||A.host||j.length>1)&&("."===l||".."===l)||""===l,d=0,h=j.length;h>=0;h--)l=j[h],"."===l?j.splice(h,1):".."===l?(j.splice(h,1),d++):d&&(j.splice(h,1),d--);if(!s&&!x)for(;d--;d)j.unshift("..");!s||""===j[0]||j[0]&&"/"===j[0].charAt(0)||j.unshift(""),Y&&"/"!==j.join("/").substr(-1)&&j.push("");var S=""===j[0]||j[0]&&"/"===j[0].charAt(0);if(w){t.hostname=t.host=S?"":j.length?j.shift():"";var L=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return s=s||t.host&&j.length,s&&!S&&j.unshift(""),j.length?t.pathname=j.join("/"):(t.pathname=null,t.path=null),N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=A.auth||t.auth,t.slashes=t.slashes||A.slashes,t.href=t.format(),t},I.prototype.parseHost=function(){var A=this.host,M=n.exec(A);M&&(M=M[0],":"!==M&&(this.port=M.substr(1)),A=A.substr(0,A.length-M.length)),A&&(this.hostname=A)}},function(A,M){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};A.exports=function(A,M){return"number"!=typeof M||t[A]?M:M+"px"}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M,t){return P.LoggedIn()?t():(location.pathname!==z.minioBrowserPrefix&&location.pathname!==z.minioBrowserPrefix+"/"||M(z.minioBrowserPrefix+"/login"),t())}function i(A,M){P.LoggedIn()&&M(""+z.minioBrowserPrefix)}function T(){q<2&&setTimeout(function(){document.querySelector(".page-load").classList.add("pl-"+q),q++,T()},K[q])}t(498);var E=t(1),N=g(E),o=t(16),n=g(o),C=t(484),c=g(C),D=t(125),a=g(D),B=t(230),Q=g(B),r=t(190),s=g(r),x=t(191),j=g(x),y=t(65),u=g(y),w=t(187),L=g(w),l=t(393),Y=g(l),d=t(22),h=g(d),S=t(42),z=(g(S),t(26)),U=t(19),p=I(U),O=t(255),m=g(O),F=t(245),f=g(F),k=t(241),R=g(k),J=t(497),G=(g(J),t(131)),H=g(G),b=t(60),X=g(b);window.Web=H.default;var v=(0,Q.default)(c.default)(a.default)(m.default),W=(0,h.default)(function(A){return A})(R.default),V=(0,h.default)(function(A){return A})(f.default),P=new H.default(window.location.protocol+"//"+window.location.host+z.minioBrowserPrefix+"/webrpc",v.dispatch);window.web=P,v.dispatch(p.setWeb(P));var Z=function(A){return N.default.createElement("div",null,A.children)};n.default.render(N.default.createElement(Y.default,{store:v,web:P},N.default.createElement(j.default,{history:u.default},N.default.createElement(s.default,{path:"/",component:Z},N.default.createElement(s.default,{path:"minio",component:Z},N.default.createElement(L.default,{component:W,onEnter:e}),N.default.createElement(s.default,{path:"login",component:V,onEnter:i}),N.default.createElement(s.default,{path:":bucket",component:W,onEnter:e}),N.default.createElement(s.default,{path:":bucket/*",component:W,onEnter:e}))))),document.getElementById("root"));var K=[0,400],q=0;T(),X.default.getItem("newlyUpdated")&&(v.dispatch(p.showAlert({type:"success",message:"Updated to the latest UI Version."})),X.default.removeItem("newlyUpdated"))},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t-1})))}},{key:"selectPrefix",value:function(A,M){A.preventDefault();var t=this.props,I=(t.dispatch,t.currentPath),g=(t.web,t.currentBucket),e=encodeURI(M);if(M.endsWith("/")||""===M){if(M===I)return;D.default.push(TA.pathJoin(g,e))}else window.location=window.location.origin+"/minio/download/"+g+"/"+e+"?token="+DA.default.getItem("token")}},{key:"makeBucket",value:function(A){A.preventDefault();var M=this.refs.makeBucketRef.value;this.refs.makeBucketRef.value="";var t=this.props,I=t.web,g=t.dispatch;this.hideMakeBucketModal(),I.MakeBucket({bucketName:M}).then(function(){g(eA.addBucket(M)),g(eA.selectBucket(M))}).catch(function(A){return g(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideMakeBucketModal",value:function(){var A=this.props.dispatch;A(eA.hideMakeBucketModal())}},{key:"showMakeBucketModal",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showMakeBucketModal())}},{key:"showAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showAbout())}},{key:"hideAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAbout())}},{key:"showBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showBucketPolicy())}},{key:"hideBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideBucketPolicy())}},{key:"uploadFile",value:function(A){A.preventDefault();var M=this.props,t=M.dispatch,I=M.buckets;if(0===I.length)return void t(eA.showAlert({type:"danger",message:"Bucket needs to be created before trying to upload files."}));var g=A.target.files[0];A.target.value=null,this.xhr=new XMLHttpRequest,t(eA.uploadFile(g,this.xhr))}},{key:"removeObject",value:function(){var A=this,M=this.props,t=M.web,I=M.dispatch,g=M.currentPath,e=M.currentBucket,i=M.deleteConfirmation;t.RemoveObject({bucketName:e,objectName:i.object}).then(function(){A.hideDeleteConfirmation(),I(eA.selectPrefix(g))}).catch(function(A){return I(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideAlert",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAlert())}},{key:"showDeleteConfirmation",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.showDeleteConfirmation(M))}},{key:"hideDeleteConfirmation",value:function(){var A=this.props.dispatch;A(eA.hideDeleteConfirmation())}},{key:"shareObject",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.shareObject(M))}},{key:"hideShareObjectModal",value:function(){var A=this.props.dispatch;A(eA.hideShareObject())}},{key:"dataType",value:function(A,M){return NA.getDataType(A,M)}},{key:"sortObjectsByName",value:function(A){var M=this.props,t=M.dispatch,I=M.objects,g=M.sortNameOrder;t(eA.setObjects(TA.sortObjectsByName(I,!g))),t(eA.setSortNameOrder(!g))}},{key:"sortObjectsBySize",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortSizeOrder;M(eA.setObjects(TA.sortObjectsBySize(t,!I))),M(eA.setSortSizeOrder(!I))}},{key:"sortObjectsByDate",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortDateOrder;M(eA.setObjects(TA.sortObjectsByDate(t,!I))),M(eA.setSortDateOrder(!I))}},{key:"logout",value:function(A){var M=this.props.web;A.preventDefault(),M.Logout(),D.default.push(oA.minioBrowserPrefix+"/login")}},{key:"landingPage",value:function(A){A.preventDefault(),this.props.dispatch(eA.selectBucket(this.props.buckets[0]))}},{key:"fullScreen",value:function(A){A.preventDefault();var M=document.documentElement;M.requestFullscreen&&M.requestFullscreen(),M.mozRequestFullScreen&&M.mozRequestFullScreen(),M.webkitRequestFullscreen&&M.webkitRequestFullscreen(),M.msRequestFullscreen&&M.msRequestFullscreen()}},{key:"toggleSidebar",value:function(A){this.props.dispatch(eA.setSidebarStatus(A))}},{key:"hideSidebar",value:function(A){var M=A||window.event,t=M.srcElement||M.target;3===t.nodeType&&(t=t.parentNode);var I=t.id;"feh-trigger"!==I&&this.props.dispatch(eA.setSidebarStatus(!1))}},{key:"showSettings",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showSettings())}},{key:"showMessage",value:function(){var A=this.props.dispatch;A(eA.showAlert({type:"success",message:"Link copied to clipboard!"})),this.hideShareObjectModal()}},{key:"selectTexts",value:function(){this.refs.copyTextInput.select()}},{key:"handleExpireValue",value:function(A,M){M===-1?this.refs[A].stepDown(1):this.refs[A].stepUp(1),7==this.refs.expireDays.value&&(this.refs.expireHours.value=0,this.refs.expireMins.value=0)}},{key:"render",value:function(){var A=this.props.storageInfo,M=A.total,t=A.free,I=this.props,g=I.showMakeBucketModal,e=I.alert,i=I.sortNameOrder,T=I.sortSizeOrder,E=I.sortDateOrder,N=I.showAbout,n=I.showBucketPolicy,c=this.props.serverInfo,D=c.version,a=c.memory,Q=c.platform,r=c.runtime,x=this.props.sidebarStatus,y=this.props.showSettings,w=this.props,l=w.policies,d=w.currentBucket,S=(w.currentPath,this.props.deleteConfirmation),U=this.props.shareObject,p=this.props,O=p.web,F=p.prefixWritable,k=y?o.default.createElement(V.default,null):o.default.createElement("noscript",null),J=o.default.createElement(L.default,{className:(0,C.default)({alert:!0,animated:!0,fadeInDown:e.show,fadeOutUp:!e.show}),bsStyle:e.type,onDismiss:this.hideAlert.bind(this)},o.default.createElement("div",{className:"text-center"},e.message));e.message||(J="");var H=(o.default.createElement(h.default,{id:"tt-sign-out"},"Sign out"),o.default.createElement(h.default,{id:"tt-upload-file"},"Upload file")),X=o.default.createElement(h.default,{id:"tt-create-bucket"},"Create bucket"),W="",P="",K="",_=M-t,AA=_/M*100+"%";O.LoggedIn()?P=o.default.createElement($.default,{fullScreenFunc:this.fullScreen.bind(this),aboutFunc:this.showAbout.bind(this),settingsFunc:this.showSettings.bind(this),logoutFunc:this.logout.bind(this)}):W=o.default.createElement("a",{className:"btn btn-danger",href:"/minio/login"},"Login"),O.LoggedIn()&&(K=o.default.createElement("div",{className:"feh-usage"},o.default.createElement("div",{className:"fehu-chart"},o.default.createElement("div",{style:{width:AA}})),o.default.createElement("ul",null,o.default.createElement("li",null,"Used:",B.default.filesize(M-t)),o.default.createElement("li",{className:"pull-right"},"Free:",B.default.filesize(M-_)))));var tA="";return O.LoggedIn()?tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," "))),o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-bucket",onClick:this.showMakeBucketModal.bind(this)},o.default.createElement("i",{className:"fa fa-hdd-o"}))))):F&&(tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," ")))))),o.default.createElement("div",{className:(0,C.default)({"file-explorer":!0,toggled:x})},o.default.createElement(R.default,{landingPage:this.landingPage.bind(this),searchBuckets:this.searchBuckets.bind(this),selectBucket:this.selectBucket.bind(this),clickOutside:this.hideSidebar.bind(this),showPolicy:this.showBucketPolicy.bind(this)}),o.default.createElement("div",{className:"fe-body"},o.default.createElement(m.default,null,J,o.default.createElement("header",{className:"fe-header-mobile hidden-lg hidden-md"},o.default.createElement("div",{id:"feh-trigger",className:"feh-trigger "+(0,C.default)({"feht-toggled":x}),onClick:this.toggleSidebar.bind(this,!x)},o.default.createElement("div",{className:"feht-lines"},o.default.createElement("div",{className:"top"}),o.default.createElement("div",{className:"center"}),o.default.createElement("div",{className:"bottom"}))),o.default.createElement("img",{className:"mh-logo",src:IA.default,alt:""})),o.default.createElement("header",{className:"fe-header"},o.default.createElement(G.default,{selectPrefix:this.selectPrefix.bind(this)}),K,o.default.createElement("ul",{className:"feh-actions"},o.default.createElement(b.default,null),W,P)),o.default.createElement("div",{className:"feb-container"},o.default.createElement("header",{className:"fesl-row","data-type":"folder"},o.default.createElement("div",{className:"fesl-item fi-name",onClick:this.sortObjectsByName.bind(this),"data-sort":"name"},"Name",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-alpha-desc":i,"fa-sort-alpha-asc":!i})})),o.default.createElement("div",{className:"fesl-item fi-size",onClick:this.sortObjectsBySize.bind(this),"data-sort":"size"},"Size",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-amount-desc":T,"fa-sort-amount-asc":!T})})),o.default.createElement("div",{className:"fesl-item fi-modified",onClick:this.sortObjectsByDate.bind(this),"data-sort":"last-modified"},"Last Modified",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-numeric-desc":E,"fa-sort-numeric-asc":!E})})),o.default.createElement("div",{className:"fesl-item fi-actions"}))),o.default.createElement("div",{className:"feb-container"},o.default.createElement(f.default,{dataType:this.dataType.bind(this),selectPrefix:this.selectPrefix.bind(this),showDeleteConfirmation:this.showDeleteConfirmation.bind(this),shareObject:this.shareObject.bind(this)})),o.default.createElement(v.default,null),tA,o.default.createElement(s.default,{className:"modal-create-bucket",bsSize:"small",animation:!1,show:g,onHide:this.hideMakeBucketModal.bind(this)},o.default.createElement("button",{className:"close close-alt",onClick:this.hideMakeBucketModal.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement(j.default,null,o.default.createElement("form",{onSubmit:this.makeBucket.bind(this)},o.default.createElement("div",{className:"input-group"},o.default.createElement("input",{className:"ig-text",type:"text",ref:"makeBucketRef",placeholder:"Bucket Name",autoFocus:!0}),o.default.createElement("i",{className:"ig-helpers"}))))),o.default.createElement(s.default,{className:"modal-about modal-dark",animation:!1,show:N,onHide:this.hideAbout.bind(this)},o.default.createElement("button",{className:"close",onClick:this.hideAbout.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement("div",{className:"ma-inner"},o.default.createElement("div",{className:"mai-item hidden-xs"},o.default.createElement("a",{href:"https://minio.io",target:"_blank"},o.default.createElement("img",{className:"maii-logo",src:IA.default,alt:""}))),o.default.createElement("div",{className:"mai-item"},o.default.createElement("ul",{className:"maii-list"},o.default.createElement("li",null,o.default.createElement("div",null,"Version"),o.default.createElement("small",null,D)),o.default.createElement("li",null,o.default.createElement("div",null,"Memory"),o.default.createElement("small",null,a)),o.default.createElement("li",null,o.default.createElement("div",null,"Platform"),o.default.createElement("small",null,Q)),o.default.createElement("li",null,o.default.createElement("div",null,"Runtime"),o.default.createElement("small",null,r)))))),o.default.createElement(s.default,{className:"modal-policy",animation:!1,show:n,onHide:this.hideBucketPolicy.bind(this)},o.default.createElement(u.default,null,"Bucket Policy (",d,")",o.default.createElement("button",{className:"close close-alt",onClick:this.hideBucketPolicy.bind(this)},o.default.createElement("span",null,"×"))),o.default.createElement("div",{className:"pm-body"},o.default.createElement(Z.default,{bucket:d}),l.map(function(A,M){return o.default.createElement(q.default,{key:M,prefix:A.prefix,policy:A.policy})}))),o.default.createElement(MA.default,{show:S.show,icon:"fa fa-exclamation-triangle mci-red",text:"Are you sure you want to delete?",sub:"This cannot be undone!",okText:"Delete",cancelText:"Cancel",okHandler:this.removeObject.bind(this),cancelHandler:this.hideDeleteConfirmation.bind(this)}),o.default.createElement(s.default,{show:U.show,animation:!1,onHide:this.hideShareObjectModal.bind(this),bsSize:"small"},o.default.createElement(u.default,null,"Share Object"),o.default.createElement(j.default,null,o.default.createElement("div",{className:"input-group copy-text"},o.default.createElement("label",null,"Shareable Link"),o.default.createElement("input",{type:"text",ref:"copyTextInput",readOnly:"readOnly",value:window.location.protocol+"//"+U.url,onClick:this.selectTexts.bind(this)})),o.default.createElement("div",{className:"input-group",style:{display:O.LoggedIn()?"block":"none"}},o.default.createElement("label",null,"Expires in"),o.default.createElement("div",{className:"set-expire"},o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireDays",1)}),o.default.createElement("div",{className:"set-expire-title"},"Days"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireDays",type:"number",min:0,max:7,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireDays",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireHours",1)}),o.default.createElement("div",{className:"set-expire-title"},"Hours"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireHours",type:"number",min:0,max:24,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireHours",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireMins",1)}),o.default.createElement("div",{className:"set-expire-title"},"Minutes"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireMins",type:"number",min:1,max:60,defaultValue:45})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireMins",-1)}))))),o.default.createElement("div",{className:"modal-footer"},o.default.createElement(CA.default,{text:U.url,onCopy:this.showMessage.bind(this)},o.default.createElement("button",{className:"btn btn-success"},"Copy Link")),o.default.createElement("button",{className:"btn btn-link",onClick:this.hideShareObjectModal.bind(this)},"Cancel"))),k)))}}]),M}(o.default.Component);M.default=aA},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(91),N=I(E),o=function(A){var M=A.fullScreenFunc,t=A.aboutFunc,I=A.settingsFunc,g=A.logoutFunc;return e.default.createElement("li",null,e.default.createElement(N.default,{pullRight:!0,id:"top-right-menu"},e.default.createElement(N.default.Toggle,{noCaret:!0},e.default.createElement("i",{className:"fa fa-reorder"})),e.default.createElement(N.default.Menu,{className:"dropdown-menu-right"},e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://github.com/minio/miniobrowser"},"Github ",e.default.createElement("i",{className:"fa fa-github"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:M},"Fullscreen ",e.default.createElement("i",{className:"fa fa-expand"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://docs.minio.io/"},"Documentation ",e.default.createElement("i",{className:"fa fa-book"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://slack.minio.io"},"Ask for help ",e.default.createElement("i",{className:"fa fa-question-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:t},"About ",e.default.createElement("i",{className:"fa fa-info-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:I},"Settings ",e.default.createElement("i",{className:"fa fa-cog"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:g},"Sign Out ",e.default.createElement("i",{className:"fa fa-sign-out"}))))))};M.default=(0,T.default)(function(A){return A})(o)},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(95),N=I(E),o=t(94),n=I(o),C=function(A){var M=A.latestUiVersion;return M===currentUiVersion?e.default.createElement("noscript",null):e.default.createElement("li",{className:"hidden-xs hidden-sm"},e.default.createElement("a",{href:""},e.default.createElement(n.default,{placement:"left",overlay:e.default.createElement(N.default,{id:"tt-version-update"},"New update available. Click to refresh.")}," ",e.default.createElement("i",{className:"fa fa-refresh"})," ")))};M.default=(0,T.default)(function(A){return{latestUiVersion:A.latestUiVersion}})(C)},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function"); -}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{buckets:[],visibleBuckets:[],objects:[],storageInfo:{},serverInfo:{},currentBucket:"",currentPath:"",showMakeBucketModal:!1,uploads:{},alert:{show:!1,type:"danger",message:""},loginError:!1,sortNameOrder:!1,sortSizeOrder:!1,sortDateOrder:!1,latestUiVersion:currentUiVersion,sideBarActive:!1,loginRedirectPath:E.minioBrowserPrefix,settings:{accessKey:"",secretKey:"",secretKeyVisible:!1},showSettings:!1,policies:[],deleteConfirmation:{object:"",show:!1},shareObject:{show:!1,url:"",expiry:604800},prefixWritable:!1},M=arguments[1],t=Object.assign({},A);switch(M.type){case T.SET_WEB:t.web=M.web;break;case T.SET_BUCKETS:t.buckets=M.buckets;break;case T.ADD_BUCKET:t.buckets=[M.bucket].concat(e(t.buckets)),t.visibleBuckets=[M.bucket].concat(e(t.visibleBuckets));break;case T.SET_VISIBLE_BUCKETS:t.visibleBuckets=M.visibleBuckets;break;case T.SET_CURRENT_BUCKET:t.currentBucket=M.currentBucket;break;case T.SET_OBJECTS:t.objects=M.objects;break;case T.SET_CURRENT_PATH:t.currentPath=M.currentPath;break;case T.SET_STORAGE_INFO:t.storageInfo=M.storageInfo;break;case T.SET_SERVER_INFO:t.serverInfo=M.serverInfo;break;case T.SHOW_MAKEBUCKET_MODAL:t.showMakeBucketModal=M.showMakeBucketModal;break;case T.UPLOAD_PROGRESS:t.uploads=Object.assign({},t.uploads),t.uploads[M.slug].loaded=M.loaded;break;case T.ADD_UPLOAD:t.uploads=Object.assign({},t.uploads,g({},M.slug,{loaded:0,size:M.size,xhr:M.xhr,name:M.name}));break;case T.STOP_UPLOAD:t.uploads=Object.assign({},t.uploads),delete t.uploads[M.slug];break;case T.SET_ALERT:t.alert.alertTimeout&&clearTimeout(t.alert.alertTimeout),M.alert.show?t.alert=M.alert:t.alert=Object.assign({},t.alert,{show:!1});break;case T.SET_LOGIN_ERROR:t.loginError=!0;break;case T.SET_SHOW_ABORT_MODAL:t.showAbortModal=M.showAbortModal;break;case T.SHOW_ABOUT:t.showAbout=M.showAbout;break;case T.SET_SORT_NAME_ORDER:t.sortNameOrder=M.sortNameOrder;break;case T.SET_SORT_SIZE_ORDER:t.sortSizeOrder=M.sortSizeOrder;break;case T.SET_SORT_DATE_ORDER:t.sortDateOrder=M.sortDateOrder;break;case T.SET_LATEST_UI_VERSION:t.latestUiVersion=M.latestUiVersion;break;case T.SET_SIDEBAR_STATUS:t.sidebarStatus=M.sidebarStatus;break;case T.SET_LOGIN_REDIRECT_PATH:t.loginRedirectPath=M.path;case T.SET_LOAD_BUCKET:t.loadBucket=M.loadBucket;break;case T.SET_LOAD_PATH:t.loadPath=M.loadPath;break;case T.SHOW_SETTINGS:t.showSettings=M.showSettings;break;case T.SET_SETTINGS:t.settings=Object.assign({},t.settings,M.settings);break;case T.SHOW_BUCKET_POLICY:t.showBucketPolicy=M.showBucketPolicy;break;case T.SET_POLICIES:t.policies=M.policies;break;case T.DELETE_CONFIRMATION:t.deleteConfirmation=Object.assign({},M.payload);break;case T.SET_SHARE_OBJECT:t.shareObject=Object.assign({},M.shareObject);break;case T.SET_PREFIX_WRITABLE:t.prefixWritable=M.prefixWritable}return t}},function(A,M,t){A.exports={default:t(260),__esModule:!0}},function(A,M,t){t(270),A.exports=t(49).Object.assign},function(A,M,t){var I=t(80);A.exports=function(A,M){return I.create(A,M)}},function(A,M,t){t(271),A.exports=t(49).Object.keys},function(A,M,t){t(272),A.exports=t(49).Object.setPrototypeOf},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M,t){var I=t(136);A.exports=function(A){if(!I(A))throw TypeError(A+" is not an object!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(263);A.exports=Object("z").propertyIsEnumerable(0)?Object:function(A){return"String"==I(A)?A.split(""):Object(A)}},function(A,M,t){var I=t(80),g=t(137),e=t(266);A.exports=t(135)(function(){var A=Object.assign,M={},t={},I=Symbol(),g="abcdefghijklmnopqrst";return M[I]=7,g.split("").forEach(function(A){t[A]=A}),7!=A({},M)[I]||Object.keys(A({},t)).join("")!=g})?function(A,M){for(var t=g(A),i=arguments,T=i.length,E=1,N=I.getKeys,o=I.getSymbols,n=I.isEnum;T>E;)for(var C,c=e(i[E++]),D=o?N(c).concat(o(c)):N(c),a=D.length,B=0;a>B;)n.call(c,C=D[B++])&&(t[C]=c[C]);return t}:Object.assign},function(A,M,t){var I=t(79),g=t(49),e=t(135);A.exports=function(A,M){var t=(g.Object||{})[A]||Object[A],i={};i[A]=M(t),I(I.S+I.F*e(function(){t(1)}),"Object",i)}},function(A,M,t){var I=t(80).getDesc,g=t(136),e=t(262),i=function(A,M){if(e(A),!g(M)&&null!==M)throw TypeError(M+": can't set as prototype!")};A.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(A,M,g){try{g=t(134)(Function.call,I(Object.prototype,"__proto__").set,2),g(A,[]),M=!(A instanceof Array)}catch(A){M=!0}return function(A,t){return i(A,t),M?A.__proto__=t:g(A,t),A}}({},!1):void 0),check:i}},function(A,M,t){var I=t(79);I(I.S+I.F,"Object",{assign:t(267)})},function(A,M,t){var I=t(137);t(268)("keys",function(A){return function(M){return A(I(M))}})},function(A,M,t){var I=t(79);I(I.S,"Object",{setPrototypeOf:t(269).set})},function(A,M,t){function I(A){if(A)return g(A); -}function g(A){for(var M in I.prototype)A[M]=I.prototype[M];return A}A.exports=I,I.prototype.on=I.prototype.addEventListener=function(A,M){return this._callbacks=this._callbacks||{},(this._callbacks["$"+A]=this._callbacks["$"+A]||[]).push(M),this},I.prototype.once=function(A,M){function t(){this.off(A,t),M.apply(this,arguments)}return t.fn=M,this.on(A,t),this},I.prototype.off=I.prototype.removeListener=I.prototype.removeAllListeners=I.prototype.removeEventListener=function(A,M){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+A];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+A],this;for(var I,g=0;g",'"',"` + "`" + `"," ","\r","\n","\t"],D=["{","}","|","\\","^","` + "`" + `"].concat(c),a=["'"].concat(D),B=["%","/","?",";","#"].concat(a),Q=["/","?","#"],r=255,s=/^[+a-z0-9A-Z_-]{0,63}$/,x=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,j={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},u={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=t(360);I.prototype.parse=function(A,M,t){if(!N.isString(A))throw new TypeError("Parameter 'url' must be a string, not "+typeof A);var I=A.indexOf("?"),g=I!==-1&&I127?"x":O[F];if(!m.match(s)){var k=U.slice(0,Y),R=U.slice(Y+1),J=O.match(x);J&&(k.push(J[1]),R.unshift(J[2])),R.length&&(T="/"+R.join(".")+T),this.hostname=k.join(".");break}}}this.hostname.length>r?this.hostname="":this.hostname=this.hostname.toLowerCase(),z||(this.hostname=E.toASCII(this.hostname));var G=this.port?":"+this.port:"",H=this.hostname||"";this.host=H+G,this.href+=this.host,z&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==T[0]&&(T="/"+T))}if(!j[D])for(var Y=0,p=a.length;Y0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return t.search=A.search,t.query=A.query,N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!j.length)return t.pathname=null,t.search?t.path="/"+t.search:t.path=null,t.href=t.format(),t;for(var l=j.slice(-1)[0],Y=(t.host||A.host||j.length>1)&&("."===l||".."===l)||""===l,d=0,h=j.length;h>=0;h--)l=j[h],"."===l?j.splice(h,1):".."===l?(j.splice(h,1),d++):d&&(j.splice(h,1),d--);if(!s&&!x)for(;d--;d)j.unshift("..");!s||""===j[0]||j[0]&&"/"===j[0].charAt(0)||j.unshift(""),Y&&"/"!==j.join("/").substr(-1)&&j.push("");var S=""===j[0]||j[0]&&"/"===j[0].charAt(0);if(w){t.hostname=t.host=S?"":j.length?j.shift():"";var L=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return s=s||t.host&&j.length,s&&!S&&j.unshift(""),j.length?t.pathname=j.join("/"):(t.pathname=null,t.path=null),N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=A.auth||t.auth,t.slashes=t.slashes||A.slashes,t.href=t.format(),t},I.prototype.parseHost=function(){var A=this.host,M=n.exec(A);M&&(M=M[0],":"!==M&&(this.port=M.substr(1)),A=A.substr(0,A.length-M.length)),A&&(this.hostname=A)}},function(A,M){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};A.exports=function(A,M){return"number"!=typeof M||t[A]?M:M+"px"}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M,t){return P.LoggedIn()?t():(location.pathname!==z.minioBrowserPrefix&&location.pathname!==z.minioBrowserPrefix+"/"||M(z.minioBrowserPrefix+"/login"),t())}function i(A,M){P.LoggedIn()&&M(""+z.minioBrowserPrefix)}function T(){q<2&&setTimeout(function(){document.querySelector(".page-load").classList.add("pl-"+q),q++,T()},K[q])}t(498);var E=t(1),N=g(E),o=t(16),n=g(o),C=t(484),c=g(C),D=t(125),a=g(D),B=t(230),Q=g(B),r=t(190),s=g(r),x=t(191),j=g(x),y=t(65),u=g(y),w=t(187),L=g(w),l=t(393),Y=g(l),d=t(22),h=g(d),S=t(42),z=(g(S),t(26)),U=t(19),p=I(U),O=t(255),m=g(O),F=t(245),f=g(F),k=t(241),R=g(k),J=t(497),G=(g(J),t(131)),H=g(G),b=t(60),X=g(b);window.Web=H.default;var v=(0,Q.default)(c.default)(a.default)(m.default),W=(0,h.default)(function(A){return A})(R.default),V=(0,h.default)(function(A){return A})(f.default),P=new H.default(window.location.protocol+"//"+window.location.host+z.minioBrowserPrefix+"/webrpc",v.dispatch);window.web=P,v.dispatch(p.setWeb(P));var Z=function(A){return N.default.createElement("div",null,A.children)};n.default.render(N.default.createElement(Y.default,{store:v,web:P},N.default.createElement(j.default,{history:u.default},N.default.createElement(s.default,{path:"/",component:Z},N.default.createElement(s.default,{path:"minio",component:Z},N.default.createElement(L.default,{component:W,onEnter:e}),N.default.createElement(s.default,{path:"login",component:V,onEnter:i}),N.default.createElement(s.default,{path:":bucket",component:W,onEnter:e}),N.default.createElement(s.default,{path:":bucket/*",component:W,onEnter:e}))))),document.getElementById("root"));var K=[0,400],q=0;T(),X.default.getItem("newlyUpdated")&&(v.dispatch(p.showAlert({type:"success",message:"Updated to the latest UI Version."})),X.default.removeItem("newlyUpdated"))},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t-1})))}},{key:"selectPrefix",value:function(A,M){A.preventDefault();var t=this.props,I=(t.dispatch,t.currentPath),g=(t.web,t.currentBucket),e=encodeURI(M);if(M.endsWith("/")||""===M){if(M===I)return;D.default.push(TA.pathJoin(g,e))}else window.location=window.location.origin+"/minio/download/"+g+"/"+e+"?token="+DA.default.getItem("token")}},{key:"makeBucket",value:function(A){A.preventDefault();var M=this.refs.makeBucketRef.value;this.refs.makeBucketRef.value="";var t=this.props,I=t.web,g=t.dispatch;this.hideMakeBucketModal(),I.MakeBucket({bucketName:M}).then(function(){g(eA.addBucket(M)),g(eA.selectBucket(M))}).catch(function(A){return g(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideMakeBucketModal",value:function(){var A=this.props.dispatch;A(eA.hideMakeBucketModal())}},{key:"showMakeBucketModal",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showMakeBucketModal())}},{key:"showAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showAbout())}},{key:"hideAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAbout())}},{key:"showBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showBucketPolicy())}},{key:"hideBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideBucketPolicy())}},{key:"uploadFile",value:function(A){A.preventDefault();var M=this.props,t=M.dispatch,I=M.buckets;if(0===I.length)return void t(eA.showAlert({type:"danger",message:"Bucket needs to be created before trying to upload files."}));var g=A.target.files[0];A.target.value=null,this.xhr=new XMLHttpRequest,t(eA.uploadFile(g,this.xhr))}},{key:"removeObject",value:function(){var A=this,M=this.props,t=M.web,I=M.dispatch,g=M.currentPath,e=M.currentBucket,i=M.deleteConfirmation;t.RemoveObject({bucketName:e,objectName:i.object}).then(function(){A.hideDeleteConfirmation(),I(eA.selectPrefix(g))}).catch(function(A){return I(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideAlert",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAlert())}},{key:"showDeleteConfirmation",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.showDeleteConfirmation(M))}},{key:"hideDeleteConfirmation",value:function(){var A=this.props.dispatch;A(eA.hideDeleteConfirmation())}},{key:"shareObject",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.shareObject(M))}},{key:"hideShareObjectModal",value:function(){var A=this.props.dispatch;A(eA.hideShareObject())}},{key:"dataType",value:function(A,M){return NA.getDataType(A,M)}},{key:"sortObjectsByName",value:function(A){var M=this.props,t=M.dispatch,I=M.objects,g=M.sortNameOrder;t(eA.setObjects(TA.sortObjectsByName(I,!g))),t(eA.setSortNameOrder(!g))}},{key:"sortObjectsBySize",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortSizeOrder;M(eA.setObjects(TA.sortObjectsBySize(t,!I))),M(eA.setSortSizeOrder(!I))}},{key:"sortObjectsByDate",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortDateOrder;M(eA.setObjects(TA.sortObjectsByDate(t,!I))),M(eA.setSortDateOrder(!I))}},{key:"logout",value:function(A){var M=this.props.web;A.preventDefault(),M.Logout(),D.default.push(oA.minioBrowserPrefix+"/login")}},{key:"fullScreen",value:function(A){A.preventDefault();var M=document.documentElement;M.requestFullscreen&&M.requestFullscreen(),M.mozRequestFullScreen&&M.mozRequestFullScreen(),M.webkitRequestFullscreen&&M.webkitRequestFullscreen(),M.msRequestFullscreen&&M.msRequestFullscreen()}},{key:"toggleSidebar",value:function(A){this.props.dispatch(eA.setSidebarStatus(A))}},{key:"hideSidebar",value:function(A){var M=A||window.event,t=M.srcElement||M.target;3===t.nodeType&&(t=t.parentNode);var I=t.id;"feh-trigger"!==I&&this.props.dispatch(eA.setSidebarStatus(!1))}},{key:"showSettings",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showSettings())}},{key:"showMessage",value:function(){var A=this.props.dispatch;A(eA.showAlert({type:"success",message:"Link copied to clipboard!"})),this.hideShareObjectModal()}},{key:"selectTexts",value:function(){this.refs.copyTextInput.select()}},{key:"handleExpireValue",value:function(A,M){M===-1?this.refs[A].stepDown(1):this.refs[A].stepUp(1),7==this.refs.expireDays.value&&(this.refs.expireHours.value=0,this.refs.expireMins.value=0)}},{key:"render",value:function(){var A=this.props.storageInfo,M=A.total,t=A.free,I=this.props,g=I.showMakeBucketModal,e=I.alert,i=I.sortNameOrder,T=I.sortSizeOrder,E=I.sortDateOrder,N=I.showAbout,n=I.showBucketPolicy,c=this.props.serverInfo,D=c.version,a=c.memory,Q=c.platform,r=c.runtime,x=this.props.sidebarStatus,y=this.props.showSettings,w=this.props,l=w.policies,d=w.currentBucket,S=(w.currentPath,this.props.deleteConfirmation),U=this.props.shareObject,p=this.props,O=p.web,F=p.prefixWritable,k=y?o.default.createElement(V.default,null):o.default.createElement("noscript",null),J=o.default.createElement(L.default,{className:(0,C.default)({alert:!0,animated:!0,fadeInDown:e.show,fadeOutUp:!e.show}),bsStyle:e.type,onDismiss:this.hideAlert.bind(this)},o.default.createElement("div",{className:"text-center"},e.message));e.message||(J="");var H=(o.default.createElement(h.default,{id:"tt-sign-out"},"Sign out"),o.default.createElement(h.default,{id:"tt-upload-file"},"Upload file")),X=o.default.createElement(h.default,{id:"tt-create-bucket"},"Create bucket"),W="",P="",K="",_=M-t,AA=_/M*100+"%";O.LoggedIn()?P=o.default.createElement($.default,{fullScreenFunc:this.fullScreen.bind(this),aboutFunc:this.showAbout.bind(this),settingsFunc:this.showSettings.bind(this),logoutFunc:this.logout.bind(this)}):W=o.default.createElement("a",{className:"btn btn-danger",href:"/minio/login"},"Login"),O.LoggedIn()&&(K=o.default.createElement("div",{className:"feh-usage"},o.default.createElement("div",{className:"fehu-chart"},o.default.createElement("div",{style:{width:AA}})),o.default.createElement("ul",null,o.default.createElement("li",null,"Used:",B.default.filesize(M-t)),o.default.createElement("li",{className:"pull-right"},"Free:",B.default.filesize(M-_)))));var tA="";return O.LoggedIn()?tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," "))),o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-bucket",onClick:this.showMakeBucketModal.bind(this)},o.default.createElement("i",{className:"fa fa-hdd-o"}))))):F&&(tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," ")))))),o.default.createElement("div",{className:(0,C.default)({"file-explorer":!0,toggled:x})},o.default.createElement(R.default,{searchBuckets:this.searchBuckets.bind(this),selectBucket:this.selectBucket.bind(this),clickOutside:this.hideSidebar.bind(this),showPolicy:this.showBucketPolicy.bind(this)}),o.default.createElement("div",{className:"fe-body"},o.default.createElement(m.default,null,J,o.default.createElement("header",{className:"fe-header-mobile hidden-lg hidden-md"},o.default.createElement("div",{id:"feh-trigger",className:"feh-trigger "+(0,C.default)({"feht-toggled":x}),onClick:this.toggleSidebar.bind(this,!x)},o.default.createElement("div",{className:"feht-lines"},o.default.createElement("div",{className:"top"}),o.default.createElement("div",{className:"center"}),o.default.createElement("div",{className:"bottom"}))),o.default.createElement("img",{className:"mh-logo",src:IA.default,alt:""})),o.default.createElement("header",{className:"fe-header"},o.default.createElement(G.default,{selectPrefix:this.selectPrefix.bind(this)}),K,o.default.createElement("ul",{className:"feh-actions"},o.default.createElement(b.default,null),W,P)),o.default.createElement("div",{className:"feb-container"},o.default.createElement("header",{className:"fesl-row","data-type":"folder"},o.default.createElement("div",{className:"fesl-item fi-name",onClick:this.sortObjectsByName.bind(this),"data-sort":"name"},"Name",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-alpha-desc":i,"fa-sort-alpha-asc":!i})})),o.default.createElement("div",{className:"fesl-item fi-size",onClick:this.sortObjectsBySize.bind(this),"data-sort":"size"},"Size",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-amount-desc":T,"fa-sort-amount-asc":!T})})),o.default.createElement("div",{className:"fesl-item fi-modified",onClick:this.sortObjectsByDate.bind(this),"data-sort":"last-modified"},"Last Modified",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-numeric-desc":E,"fa-sort-numeric-asc":!E})})),o.default.createElement("div",{className:"fesl-item fi-actions"}))),o.default.createElement("div",{className:"feb-container"},o.default.createElement(f.default,{dataType:this.dataType.bind(this),selectPrefix:this.selectPrefix.bind(this),showDeleteConfirmation:this.showDeleteConfirmation.bind(this),shareObject:this.shareObject.bind(this)})),o.default.createElement(v.default,null),tA,o.default.createElement(s.default,{className:"modal-create-bucket",bsSize:"small",animation:!1,show:g,onHide:this.hideMakeBucketModal.bind(this)},o.default.createElement("button",{className:"close close-alt",onClick:this.hideMakeBucketModal.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement(j.default,null,o.default.createElement("form",{onSubmit:this.makeBucket.bind(this)},o.default.createElement("div",{className:"input-group"},o.default.createElement("input",{className:"ig-text",type:"text",ref:"makeBucketRef",placeholder:"Bucket Name",autoFocus:!0}),o.default.createElement("i",{className:"ig-helpers"}))))),o.default.createElement(s.default,{className:"modal-about modal-dark",animation:!1,show:N,onHide:this.hideAbout.bind(this)},o.default.createElement("button",{className:"close",onClick:this.hideAbout.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement("div",{className:"ma-inner"},o.default.createElement("div",{className:"mai-item hidden-xs"},o.default.createElement("a",{href:"https://minio.io",target:"_blank"},o.default.createElement("img",{className:"maii-logo",src:IA.default,alt:""}))),o.default.createElement("div",{className:"mai-item"},o.default.createElement("ul",{className:"maii-list"},o.default.createElement("li",null,o.default.createElement("div",null,"Version"),o.default.createElement("small",null,D)),o.default.createElement("li",null,o.default.createElement("div",null,"Memory"),o.default.createElement("small",null,a)),o.default.createElement("li",null,o.default.createElement("div",null,"Platform"),o.default.createElement("small",null,Q)),o.default.createElement("li",null,o.default.createElement("div",null,"Runtime"),o.default.createElement("small",null,r)))))),o.default.createElement(s.default,{className:"modal-policy",animation:!1,show:n,onHide:this.hideBucketPolicy.bind(this)},o.default.createElement(u.default,null,"Bucket Policy (",d,")",o.default.createElement("button",{className:"close close-alt",onClick:this.hideBucketPolicy.bind(this)},o.default.createElement("span",null,"×"))),o.default.createElement("div",{className:"pm-body"},o.default.createElement(Z.default,{bucket:d}),l.map(function(A,M){return o.default.createElement(q.default,{key:M,prefix:A.prefix,policy:A.policy})}))),o.default.createElement(MA.default,{show:S.show,icon:"fa fa-exclamation-triangle mci-red",text:"Are you sure you want to delete?",sub:"This cannot be undone!",okText:"Delete",cancelText:"Cancel",okHandler:this.removeObject.bind(this),cancelHandler:this.hideDeleteConfirmation.bind(this)}),o.default.createElement(s.default,{show:U.show,animation:!1,onHide:this.hideShareObjectModal.bind(this),bsSize:"small"},o.default.createElement(u.default,null,"Share Object"),o.default.createElement(j.default,null,o.default.createElement("div",{className:"input-group copy-text"},o.default.createElement("label",null,"Shareable Link"),o.default.createElement("input",{type:"text",ref:"copyTextInput",readOnly:"readOnly",value:window.location.protocol+"//"+U.url,onClick:this.selectTexts.bind(this)})),o.default.createElement("div",{className:"input-group",style:{display:O.LoggedIn()?"block":"none"}},o.default.createElement("label",null,"Expires in"),o.default.createElement("div",{className:"set-expire"},o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireDays",1)}),o.default.createElement("div",{className:"set-expire-title"},"Days"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireDays",type:"number",min:0,max:7,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireDays",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireHours",1)}),o.default.createElement("div",{className:"set-expire-title"},"Hours"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireHours",type:"number",min:0,max:24,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireHours",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireMins",1)}),o.default.createElement("div",{className:"set-expire-title"},"Minutes"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireMins",type:"number",min:1,max:60,defaultValue:45})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireMins",-1)}))))),o.default.createElement("div",{className:"modal-footer"},o.default.createElement(CA.default,{text:U.url,onCopy:this.showMessage.bind(this)},o.default.createElement("button",{className:"btn btn-success"},"Copy Link")),o.default.createElement("button",{className:"btn btn-link",onClick:this.hideShareObjectModal.bind(this)},"Cancel"))),k)))}}]),M}(o.default.Component);M.default=aA},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(91),N=I(E),o=function(A){var M=A.fullScreenFunc,t=A.aboutFunc,I=A.settingsFunc,g=A.logoutFunc;return e.default.createElement("li",null,e.default.createElement(N.default,{pullRight:!0,id:"top-right-menu"},e.default.createElement(N.default.Toggle,{noCaret:!0},e.default.createElement("i",{className:"fa fa-reorder"})),e.default.createElement(N.default.Menu,{className:"dropdown-menu-right"},e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://github.com/minio/miniobrowser"},"Github ",e.default.createElement("i",{className:"fa fa-github"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:M},"Fullscreen ",e.default.createElement("i",{className:"fa fa-expand"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://docs.minio.io/"},"Documentation ",e.default.createElement("i",{className:"fa fa-book"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://slack.minio.io"},"Ask for help ",e.default.createElement("i",{className:"fa fa-question-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:t},"About ",e.default.createElement("i",{className:"fa fa-info-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:I},"Settings ",e.default.createElement("i",{className:"fa fa-cog"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:g},"Sign Out ",e.default.createElement("i",{className:"fa fa-sign-out"}))))))};M.default=(0,T.default)(function(A){return A})(o)},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(95),N=I(E),o=t(94),n=I(o),C=function(A){var M=A.latestUiVersion;return M===currentUiVersion?e.default.createElement("noscript",null):e.default.createElement("li",{className:"hidden-xs hidden-sm"},e.default.createElement("a",{href:""},e.default.createElement(n.default,{placement:"left",overlay:e.default.createElement(N.default,{id:"tt-version-update"},"New update available. Click to refresh.")}," ",e.default.createElement("i",{className:"fa fa-refresh"})," ")))};M.default=(0,T.default)(function(A){return{latestUiVersion:A.latestUiVersion}})(C)},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M; +}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{buckets:[],visibleBuckets:[],objects:[],storageInfo:{},serverInfo:{},currentBucket:"",currentPath:"",showMakeBucketModal:!1,uploads:{},alert:{show:!1,type:"danger",message:""},loginError:!1,sortNameOrder:!1,sortSizeOrder:!1,sortDateOrder:!1,latestUiVersion:currentUiVersion,sideBarActive:!1,loginRedirectPath:E.minioBrowserPrefix,settings:{accessKey:"",secretKey:"",secretKeyVisible:!1},showSettings:!1,policies:[],deleteConfirmation:{object:"",show:!1},shareObject:{show:!1,url:"",expiry:604800},prefixWritable:!1},M=arguments[1],t=Object.assign({},A);switch(M.type){case T.SET_WEB:t.web=M.web;break;case T.SET_BUCKETS:t.buckets=M.buckets;break;case T.ADD_BUCKET:t.buckets=[M.bucket].concat(e(t.buckets)),t.visibleBuckets=[M.bucket].concat(e(t.visibleBuckets));break;case T.SET_VISIBLE_BUCKETS:t.visibleBuckets=M.visibleBuckets;break;case T.SET_CURRENT_BUCKET:t.currentBucket=M.currentBucket;break;case T.SET_OBJECTS:t.objects=M.objects;break;case T.SET_CURRENT_PATH:t.currentPath=M.currentPath;break;case T.SET_STORAGE_INFO:t.storageInfo=M.storageInfo;break;case T.SET_SERVER_INFO:t.serverInfo=M.serverInfo;break;case T.SHOW_MAKEBUCKET_MODAL:t.showMakeBucketModal=M.showMakeBucketModal;break;case T.UPLOAD_PROGRESS:t.uploads=Object.assign({},t.uploads),t.uploads[M.slug].loaded=M.loaded;break;case T.ADD_UPLOAD:t.uploads=Object.assign({},t.uploads,g({},M.slug,{loaded:0,size:M.size,xhr:M.xhr,name:M.name}));break;case T.STOP_UPLOAD:t.uploads=Object.assign({},t.uploads),delete t.uploads[M.slug];break;case T.SET_ALERT:t.alert.alertTimeout&&clearTimeout(t.alert.alertTimeout),M.alert.show?t.alert=M.alert:t.alert=Object.assign({},t.alert,{show:!1});break;case T.SET_LOGIN_ERROR:t.loginError=!0;break;case T.SET_SHOW_ABORT_MODAL:t.showAbortModal=M.showAbortModal;break;case T.SHOW_ABOUT:t.showAbout=M.showAbout;break;case T.SET_SORT_NAME_ORDER:t.sortNameOrder=M.sortNameOrder;break;case T.SET_SORT_SIZE_ORDER:t.sortSizeOrder=M.sortSizeOrder;break;case T.SET_SORT_DATE_ORDER:t.sortDateOrder=M.sortDateOrder;break;case T.SET_LATEST_UI_VERSION:t.latestUiVersion=M.latestUiVersion;break;case T.SET_SIDEBAR_STATUS:t.sidebarStatus=M.sidebarStatus;break;case T.SET_LOGIN_REDIRECT_PATH:t.loginRedirectPath=M.path;case T.SET_LOAD_BUCKET:t.loadBucket=M.loadBucket;break;case T.SET_LOAD_PATH:t.loadPath=M.loadPath;break;case T.SHOW_SETTINGS:t.showSettings=M.showSettings;break;case T.SET_SETTINGS:t.settings=Object.assign({},t.settings,M.settings);break;case T.SHOW_BUCKET_POLICY:t.showBucketPolicy=M.showBucketPolicy;break;case T.SET_POLICIES:t.policies=M.policies;break;case T.DELETE_CONFIRMATION:t.deleteConfirmation=Object.assign({},M.payload);break;case T.SET_SHARE_OBJECT:t.shareObject=Object.assign({},M.shareObject);break;case T.SET_PREFIX_WRITABLE:t.prefixWritable=M.prefixWritable}return t}},function(A,M,t){A.exports={default:t(260),__esModule:!0}},function(A,M,t){t(270),A.exports=t(49).Object.assign},function(A,M,t){var I=t(80);A.exports=function(A,M){return I.create(A,M)}},function(A,M,t){t(271),A.exports=t(49).Object.keys},function(A,M,t){t(272),A.exports=t(49).Object.setPrototypeOf},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M,t){var I=t(136);A.exports=function(A){if(!I(A))throw TypeError(A+" is not an object!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(263);A.exports=Object("z").propertyIsEnumerable(0)?Object:function(A){return"String"==I(A)?A.split(""):Object(A)}},function(A,M,t){var I=t(80),g=t(137),e=t(266);A.exports=t(135)(function(){var A=Object.assign,M={},t={},I=Symbol(),g="abcdefghijklmnopqrst";return M[I]=7,g.split("").forEach(function(A){t[A]=A}),7!=A({},M)[I]||Object.keys(A({},t)).join("")!=g})?function(A,M){for(var t=g(A),i=arguments,T=i.length,E=1,N=I.getKeys,o=I.getSymbols,n=I.isEnum;T>E;)for(var C,c=e(i[E++]),D=o?N(c).concat(o(c)):N(c),a=D.length,B=0;a>B;)n.call(c,C=D[B++])&&(t[C]=c[C]);return t}:Object.assign},function(A,M,t){var I=t(79),g=t(49),e=t(135);A.exports=function(A,M){var t=(g.Object||{})[A]||Object[A],i={};i[A]=M(t),I(I.S+I.F*e(function(){t(1)}),"Object",i)}},function(A,M,t){var I=t(80).getDesc,g=t(136),e=t(262),i=function(A,M){if(e(A),!g(M)&&null!==M)throw TypeError(M+": can't set as prototype!")};A.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(A,M,g){try{g=t(134)(Function.call,I(Object.prototype,"__proto__").set,2),g(A,[]),M=!(A instanceof Array)}catch(A){M=!0}return function(A,t){return i(A,t),M?A.__proto__=t:g(A,t),A}}({},!1):void 0),check:i}},function(A,M,t){var I=t(79);I(I.S+I.F,"Object",{assign:t(267)})},function(A,M,t){var I=t(137);t(268)("keys",function(A){return function(M){return A(I(M))}})},function(A,M,t){var I=t(79);I(I.S,"Object",{setPrototypeOf:t(269).set})},function(A,M,t){function I(A){if(A)return g(A)}function g(A){for(var M in I.prototype)A[M]=I.prototype[M];return A}A.exports=I,I.prototype.on=I.prototype.addEventListener=function(A,M){return this._callbacks=this._callbacks||{},(this._callbacks["$"+A]=this._callbacks["$"+A]||[]).push(M), +this},I.prototype.once=function(A,M){function t(){this.off(A,t),M.apply(this,arguments)}return t.fn=M,this.on(A,t),this},I.prototype.off=I.prototype.removeListener=I.prototype.removeAllListeners=I.prototype.removeEventListener=function(A,M){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+A];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+A],this;for(var I,g=0;g1&&(I=t[0]+"@",A=t[1]),A=A.replace(z,".");var g=A.split("."),e=T(g,M).join(".");return I+e}function N(A){for(var M,t,I=[],g=0,e=A.length;g=55296&&M<=56319&&g65535&&(A-=65536,M+=m(A>>>10&1023|55296),A=56320|1023&A),M+=m(A)}).join("")}function n(A){return A-48<10?A-22:A-65<26?A-65:A-97<26?A-97:j}function C(A,M){return A+22+75*(A<26)-((0!=M)<<5)}function c(A,M,t){var I=0;for(A=t?O(A/L):A>>1,A+=O(A/M);A>p*u>>1;I+=j)A=O(A/p);return O(I+(p+1)*A/(A+w))}function D(A){var M,t,I,g,e,T,E,N,C,D,a=[],B=A.length,Q=0,r=Y,s=l;for(t=A.lastIndexOf(d),t<0&&(t=0),I=0;I=128&&i("not-basic"),a.push(A.charCodeAt(I));for(g=t>0?t+1:0;g=B&&i("invalid-input"),N=n(A.charCodeAt(g++)),(N>=j||N>O((x-Q)/T))&&i("overflow"),Q+=N*T,C=E<=s?y:E>=s+u?u:E-s,!(NO(x/D)&&i("overflow"),T*=D;M=a.length+1,s=c(Q-e,M,0==e),O(Q/M)>x-r&&i("overflow"),r+=O(Q/M),Q%=M,a.splice(Q++,0,r)}return o(a)}function a(A){var M,t,I,g,e,T,E,o,n,D,a,B,Q,r,s,w=[];for(A=N(A),B=A.length,M=Y,t=0,e=l,T=0;T=M&&aO((x-t)/Q)&&i("overflow"),t+=(E-M)*Q,M=E,T=0;Tx&&i("overflow"),a==M){for(o=t,n=j;D=n<=e?y:n>=e+u?u:n-e,!(o= 0x80 (not a basic code point)","invalid-input":"Invalid input"},p=j-y,O=Math.floor,m=String.fromCharCode;s={version:"1.3.2",ucs2:{decode:N,encode:o},decode:D,encode:a,toASCII:Q,toUnicode:B},I=function(){return s}.call(M,t,M,A),!(void 0!==I&&(A.exports=I))}(this)}).call(M,t(128)(A),function(){return this}())},function(A,M){"use strict";A.exports={isString:function(A){return"string"==typeof A},isObject:function(A){return"object"==typeof A&&null!==A},isNull:function(A){return null===A},isNullOrUndefined:function(A){return null==A}}}]);`) -func productionIndex_bundle20170131t003809zJsBytes() ([]byte, error) { - return _productionIndex_bundle20170131t003809zJs, nil +func productionIndex_bundle20170202t110000zJsBytes() ([]byte, error) { + return _productionIndex_bundle20170202t110000zJs, nil } -func productionIndex_bundle20170131t003809zJs() (*asset, error) { - bytes, err := productionIndex_bundle20170131t003809zJsBytes() +func productionIndex_bundle20170202t110000zJs() (*asset, error) { + bytes, err := productionIndex_bundle20170202t110000zJsBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "production/index_bundle-2017-01-31T00-38-09Z.js", size: 2272159, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/index_bundle-2017-02-02T11-00-00Z.js", size: 2271935, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -370,7 +370,7 @@ func productionLoaderCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -444,7 +444,7 @@ func productionLogoSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -461,7 +461,7 @@ func productionSafariPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1485823104, 0)} + info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -522,7 +522,7 @@ var _bindata = map[string]func() (*asset, error){ "production/favicon.ico": productionFaviconIco, "production/firefox.png": productionFirefoxPng, "production/index.html": productionIndexHTML, - "production/index_bundle-2017-01-31T00-38-09Z.js": productionIndex_bundle20170131t003809zJs, + "production/index_bundle-2017-02-02T11-00-00Z.js": productionIndex_bundle20170202t110000zJs, "production/loader.css": productionLoaderCss, "production/logo.svg": productionLogoSvg, "production/safari.png": productionSafariPng, @@ -574,7 +574,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "favicon.ico": {productionFaviconIco, map[string]*bintree{}}, "firefox.png": {productionFirefoxPng, map[string]*bintree{}}, "index.html": {productionIndexHTML, map[string]*bintree{}}, - "index_bundle-2017-01-31T00-38-09Z.js": {productionIndex_bundle20170131t003809zJs, map[string]*bintree{}}, + "index_bundle-2017-02-02T11-00-00Z.js": {productionIndex_bundle20170202t110000zJs, map[string]*bintree{}}, "loader.css": {productionLoaderCss, map[string]*bintree{}}, "logo.svg": {productionLogoSvg, map[string]*bintree{}}, "safari.png": {productionSafariPng, map[string]*bintree{}}, @@ -635,6 +635,6 @@ func assetFS() *assetfs.AssetFS { panic("unreachable") } -var UIReleaseTag = "RELEASE.2017-01-31T00-38-09Z" -var UICommitID = "e9394dc22df31cdf3ecb63897204ca51b95852a8" -var UIVersion = "2017-01-31T00:38:09Z" +var UIReleaseTag = "RELEASE.2017-02-02T11-00-00Z" +var UICommitID = "fc446e0b812eb1c6c56a413a3c77e818227394bd" +var UIVersion = "2017-02-02T11:00:00Z" diff --git a/browser/webpack.config.js b/browser/webpack.config.js index 9496c56ef..3ccdaba0b 100644 --- a/browser/webpack.config.js +++ b/browser/webpack.config.js @@ -58,7 +58,6 @@ var exports = { historyApiFallback: { index: '/minio/' }, - port: 8888, proxy: { '/minio/webrpc': { target: 'http://localhost:9000', @@ -98,7 +97,7 @@ var exports = { if (process.env.NODE_ENV === 'dev') { exports.entry = [ 'webpack/hot/dev-server', - 'webpack-dev-server/client?http://localhost:8888', + 'webpack-dev-server/client?http://localhost:8080', path.resolve(__dirname, 'app/index.js') ] } From ed4fcb63f728d620d8e7cbb5f14a1e0478cffc1e Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Thu, 2 Feb 2017 19:45:00 +0100 Subject: [PATCH 40/75] Require content-length in POST & Upload requests (#3671) Avoid passing size = -1 to PutObject API by requiring content-length header in POST request (as AWS S3 does) and in Upload web handler. Post handler is modified to completely store multipart file to know its size before sending it to PutObject(). --- cmd/bucket-handlers.go | 50 ++++++++++++++++++++-------- cmd/globals.go | 3 ++ cmd/handler-utils.go | 63 ++++++++++++++++++++++-------------- cmd/jwt.go | 4 +-- cmd/post-policy_test.go | 70 ++++++++++++++++++++++++++-------------- cmd/typed-errors.go | 3 ++ cmd/web-handlers.go | 21 +++++++++--- cmd/web-handlers_test.go | 31 ++++++++++++------ 8 files changed, 166 insertions(+), 79 deletions(-) diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index db942d755..e6f5c6871 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -393,6 +393,13 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h return } + // Require Content-Length to be set in the request + size := r.ContentLength + if size < 0 { + writeErrorResponse(w, ErrMissingContentLength, r.URL) + return + } + // Here the parameter is the size of the form data that should // be loaded in memory, the remaining being put in temporary files. reader, err := r.MultipartReader() @@ -402,12 +409,28 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h return } - fileBody, fileName, formValues, err := extractPostPolicyFormValues(reader) + // Read multipart data and save in memory and in the disk if needed + form, err := reader.ReadForm(maxFormMemory) + if err != nil { + errorIf(err, "Unable to initialize multipart reader.") + writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) + return + } + + // Remove all tmp files creating during multipart upload + defer form.RemoveAll() + + // Extract all form fields + fileBody, fileName, fileSize, formValues, err := extractPostPolicyFormValues(form) if err != nil { errorIf(err, "Unable to parse form values.") writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) return } + + // Close multipart file + defer fileBody.Close() + bucket := mux.Vars(r)["bucket"] formValues["Bucket"] = bucket @@ -443,21 +466,20 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h return } - // Use rangeReader to ensure that object size is within expected range. + // Ensure that the object size is within expected range, also the file size + // should not exceed the maximum single Put size (5 GiB) lengthRange := postPolicyForm.Conditions.ContentLengthRange if lengthRange.Valid { - // If policy restricted the size of the object. - fileBody = &rangeReader{ - Reader: fileBody, - Min: lengthRange.Min, - Max: lengthRange.Max, + if fileSize < lengthRange.Min { + errorIf(err, "Unable to create object.") + writeErrorResponse(w, toAPIErrorCode(errDataTooSmall), r.URL) + return } - } else { - // Default values of min/max size of the object. - fileBody = &rangeReader{ - Reader: fileBody, - Min: 0, - Max: maxObjectSize, + + if fileSize > lengthRange.Max || fileSize > maxObjectSize { + errorIf(err, "Unable to create object.") + writeErrorResponse(w, toAPIErrorCode(errDataTooLarge), r.URL) + return } } @@ -470,7 +492,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h objectLock.Lock() defer objectLock.Unlock() - objInfo, err := objectAPI.PutObject(bucket, object, -1, fileBody, metadata, sha256sum) + objInfo, err := objectAPI.PutObject(bucket, object, fileSize, fileBody, metadata, sha256sum) if err != nil { errorIf(err, "Unable to create object.") writeErrorResponse(w, toAPIErrorCode(err), r.URL) diff --git a/cmd/globals.go b/cmd/globals.go index f2ed99dd9..be77a78db 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -59,6 +59,9 @@ const ( // can reach that size according to https://aws.amazon.com/articles/1434 maxFormFieldSize = int64(1 * humanize.MiByte) + // Limit memory allocation to store multipart data + maxFormMemory = int64(5 * humanize.MiByte) + // The maximum allowed difference between the request generation time and the server processing time globalMaxSkewTime = 15 * time.Minute ) diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index a97f0f192..7b03a7e83 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -18,7 +18,6 @@ package cmd import ( "io" - "io/ioutil" "mime/multipart" "net/http" "strings" @@ -158,33 +157,49 @@ func extractMetadataFromForm(formValues map[string]string) map[string]string { } // Extract form fields and file data from a HTTP POST Policy -func extractPostPolicyFormValues(reader *multipart.Reader) (filePart io.Reader, fileName string, formValues map[string]string, err error) { +func extractPostPolicyFormValues(form *multipart.Form) (filePart io.ReadCloser, fileName string, fileSize int64, formValues map[string]string, err error) { /// HTML Form values formValues = make(map[string]string) fileName = "" - for err == nil { - var part *multipart.Part - part, err = reader.NextPart() - if part != nil { - canonicalFormName := http.CanonicalHeaderKey(part.FormName()) - if canonicalFormName != "File" { - var buffer []byte - limitReader := io.LimitReader(part, maxFormFieldSize+1) - buffer, err = ioutil.ReadAll(limitReader) - if err != nil { - return nil, "", nil, err - } - if int64(len(buffer)) > maxFormFieldSize { - return nil, "", nil, errSizeUnexpected - } - formValues[canonicalFormName] = string(buffer) - } else { - filePart = part - fileName = part.FileName() - // As described in S3 spec, we expect file to be the last form field - break + + // Iterate over form values + for k, v := range form.Value { + canonicalFormName := http.CanonicalHeaderKey(k) + // Check if value's field exceeds S3 limit + if int64(len(v[0])) > maxFormFieldSize { + return nil, "", 0, nil, errSizeUnexpected + } + // Set the form value + formValues[canonicalFormName] = v[0] + } + + // Iterator until we find a valid File field and break + for k, v := range form.File { + canonicalFormName := http.CanonicalHeaderKey(k) + if canonicalFormName == "File" { + if len(v) == 0 { + return nil, "", 0, nil, errInvalidArgument } + // Fetch fileHeader which has the uploaded file information + fileHeader := v[0] + // Set filename + fileName = fileHeader.Filename + // Open the uploaded part + filePart, err = fileHeader.Open() + // Compute file size + fileSize, err = filePart.(io.Seeker).Seek(0, 2) + if err != nil { + return nil, "", 0, nil, err + } + // Reset Seek to the beginning + _, err = filePart.(io.Seeker).Seek(0, 0) + if err != nil { + return nil, "", 0, nil, err + } + // File found and ready for reading + break } } - return filePart, fileName, formValues, nil + + return filePart, fileName, fileSize, formValues, nil } diff --git a/cmd/jwt.go b/cmd/jwt.go index c3d80a08f..f1f0b2373 100644 --- a/cmd/jwt.go +++ b/cmd/jwt.go @@ -106,13 +106,13 @@ func isAuthTokenValid(tokenString string) bool { } func isHTTPRequestValid(req *http.Request) bool { - return webReqestAuthenticate(req) == nil + return webRequestAuthenticate(req) == nil } // Check if the request is authenticated. // Returns nil if the request is authenticated. errNoAuthToken if token missing. // Returns errAuthentication for all other errors. -func webReqestAuthenticate(req *http.Request) error { +func webRequestAuthenticate(req *http.Request) error { jwtToken, err := jwtreq.ParseFromRequest(req, jwtreq.AuthorizationHeaderExtractor, keyFuncCallback) if err != nil { if err == jwtreq.ErrNoTokenInRequest { diff --git a/cmd/post-policy_test.go b/cmd/post-policy_test.go index 60333e3a3..14018979a 100644 --- a/cmd/post-policy_test.go +++ b/cmd/post-policy_test.go @@ -342,46 +342,66 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr } testCases2 := []struct { - objectName string - data []byte - expectedRespStatus int - accessKey string - secretKey string - malformedBody bool + objectName string + data []byte + expectedRespStatus int + accessKey string + secretKey string + malformedBody bool + ignoreContentLength bool }{ // Success case. { - objectName: "test", - data: bytes.Repeat([]byte("a"), 1025), - expectedRespStatus: http.StatusNoContent, - accessKey: credentials.AccessKey, - secretKey: credentials.SecretKey, - malformedBody: false, + objectName: "test", + data: bytes.Repeat([]byte("a"), 1025), + expectedRespStatus: http.StatusNoContent, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + malformedBody: false, + ignoreContentLength: false, + }, + // Failed with Content-Length not specified. + { + objectName: "test", + data: bytes.Repeat([]byte("a"), 1025), + expectedRespStatus: http.StatusNoContent, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + malformedBody: false, + ignoreContentLength: true, }, // Failed with entity too small. { - objectName: "test", - data: bytes.Repeat([]byte("a"), 1023), - expectedRespStatus: http.StatusBadRequest, - accessKey: credentials.AccessKey, - secretKey: credentials.SecretKey, - malformedBody: false, + objectName: "test", + data: bytes.Repeat([]byte("a"), 1023), + expectedRespStatus: http.StatusBadRequest, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + malformedBody: false, + ignoreContentLength: false, }, // Failed with entity too large. { - objectName: "test", - data: bytes.Repeat([]byte("a"), (1*humanize.MiByte)+1), - expectedRespStatus: http.StatusBadRequest, - accessKey: credentials.AccessKey, - secretKey: credentials.SecretKey, - malformedBody: false, + objectName: "test", + data: bytes.Repeat([]byte("a"), (1*humanize.MiByte)+1), + expectedRespStatus: http.StatusBadRequest, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + malformedBody: false, + ignoreContentLength: false, }, } for i, testCase := range testCases2 { // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() - req, perr := newPostRequestV4WithContentLength("", bucketName, testCase.objectName, testCase.data, testCase.accessKey, testCase.secretKey) + var req *http.Request + var perr error + if testCase.ignoreContentLength { + req, perr = newPostRequestV4("", bucketName, testCase.objectName, testCase.data, testCase.accessKey, testCase.secretKey) + } else { + req, perr = newPostRequestV4WithContentLength("", bucketName, testCase.objectName, testCase.data, testCase.accessKey, testCase.secretKey) + } if perr != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PostPolicyHandler: %v", i+1, instanceType, perr) } diff --git a/cmd/typed-errors.go b/cmd/typed-errors.go index e79ab0dd6..5a7568568 100644 --- a/cmd/typed-errors.go +++ b/cmd/typed-errors.go @@ -33,6 +33,9 @@ var errContentSHA256Mismatch = errors.New("Content checksum SHA256 mismatch") // used when we deal with data larger than expected var errSizeUnexpected = errors.New("Data size larger than expected") +// used when we deal with data with unknown size +var errSizeUnspecified = errors.New("Data size is unspecified") + // When upload object size is greater than 5G in a single PUT/POST operation. var errDataTooLarge = errors.New("Object size larger than allowed limit") diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index adf9f6db7..4943fa78c 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -151,7 +151,7 @@ func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, re if objectAPI == nil { return toJSONError(errServerNotInitialized) } - authErr := webReqestAuthenticate(r) + authErr := webRequestAuthenticate(r) if authErr != nil { return toJSONError(authErr) } @@ -208,7 +208,7 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r prefix := args.Prefix + "test" // To test if GetObject/PutObject with the specified prefix is allowed. readable := isBucketActionAllowed("s3:GetObject", args.BucketName, prefix) writable := isBucketActionAllowed("s3:PutObject", args.BucketName, prefix) - authErr := webReqestAuthenticate(r) + authErr := webRequestAuthenticate(r) switch { case authErr == errAuthentication: return toJSONError(authErr) @@ -446,7 +446,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) { bucket := vars["bucket"] object := vars["object"] - authErr := webReqestAuthenticate(r) + authErr := webRequestAuthenticate(r) if authErr == errAuthentication { writeWebErrorResponse(w, errAuthentication) return @@ -456,6 +456,13 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) { return } + // Require Content-Length to be set in the request + size := r.ContentLength + if size < 0 { + writeWebErrorResponse(w, errSizeUnspecified) + return + } + // Extract incoming metadata if any. metadata := extractMetadataFromHeader(r.Header) @@ -465,7 +472,7 @@ func (web *webAPIHandlers) Upload(w http.ResponseWriter, r *http.Request) { defer objectLock.Unlock() sha256sum := "" - objInfo, err := objectAPI.PutObject(bucket, object, -1, r.Body, metadata, sha256sum) + objInfo, err := objectAPI.PutObject(bucket, object, size, r.Body, metadata, sha256sum) if err != nil { writeWebErrorResponse(w, err) return @@ -816,6 +823,12 @@ func toWebAPIError(err error) APIError { HTTPStatusCode: http.StatusForbidden, Description: err.Error(), } + } else if err == errSizeUnspecified { + return APIError{ + Code: "InvalidRequest", + HTTPStatusCode: http.StatusBadRequest, + Description: err.Error(), + } } // Convert error type to api error code. diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index fc72ab9ff..1f8c9e627 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -738,19 +738,24 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler objectName := "test.file" bucketName := getRandomBucketName() - test := func(token string) int { + test := func(token string, sendContentLength bool) int { rec := httptest.NewRecorder() - var req *http.Request - req, err = http.NewRequest("PUT", "/minio/upload/"+bucketName+"/"+objectName, nil) - if err != nil { - t.Fatalf("Cannot create upload request, %v", err) + req, rErr := http.NewRequest("PUT", "/minio/upload/"+bucketName+"/"+objectName, nil) + if rErr != nil { + t.Fatalf("Cannot create upload request, %v", rErr) } - req.Header.Set("Content-Length", strconv.Itoa(len(content))) req.Header.Set("x-amz-date", "20160814T114029Z") req.Header.Set("Accept", "*/*") + req.Body = ioutil.NopCloser(bytes.NewReader(content)) + if !sendContentLength { + req.ContentLength = -1 + } else { + req.ContentLength = int64(len(content)) + } + if token != "" { req.Header.Set("Authorization", "Bearer "+authorization) } @@ -765,7 +770,7 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler } // Authenticated upload should succeed. - code := test(authorization) + code := test(authorization, true) if code != http.StatusOK { t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) } @@ -780,8 +785,14 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler t.Fatalf("The upload file is different from the download file") } + // Authenticated upload without content-length should fail + code = test(authorization, false) + if code != http.StatusBadRequest { + t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) + } + // Unauthenticated upload should fail. - code = test("") + code = test("", true) if code != http.StatusForbidden { t.Fatalf("Expected the response status to be 403, but instead found `%d`", code) } @@ -794,13 +805,13 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler globalBucketPolicies.SetBucketPolicy(bucketName, policyChange{false, &policy}) // Unauthenticated upload with WRITE policy should succeed. - code = test("") + code = test("", true) if code != http.StatusOK { t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) } } -// Wrapper for calling Upload Handler +// Wrapper for calling Download Handler func TestWebHandlerDownload(t *testing.T) { ExecObjectLayerTest(t, testDownloadWebHandler) } From b6ebf2aba8e11f1336391140f93dcd0fd9d05287 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Sat, 4 Feb 2017 07:53:30 +0100 Subject: [PATCH 41/75] server-mux: Simplify graceful shutdown behavior (#3681) `*http.Server` is no more used, doing some cleanup. --- cmd/server-main.go | 4 +- cmd/server-main_test.go | 5 +- cmd/server-mux.go | 121 +++++++++---------------------- cmd/server-mux_test.go | 139 +++++++++++++++++------------------- cmd/server-startup-utils.go | 5 +- 5 files changed, 105 insertions(+), 169 deletions(-) diff --git a/cmd/server-main.go b/cmd/server-main.go index 1971ef442..e54143d73 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -449,8 +449,8 @@ func serverMain(c *cli.Context) { initGlobalAdminPeers(endpoints) // Determine API endpoints where we are going to serve the S3 API from. - apiEndPoints, err := finalizeAPIEndpoints(apiServer.Server) - fatalIf(err, "Unable to finalize API endpoints for %s", apiServer.Server.Addr) + apiEndPoints, err := finalizeAPIEndpoints(apiServer.Addr) + fatalIf(err, "Unable to finalize API endpoints for %s", apiServer.Addr) // Set the global API endpoints value. globalAPIEndpoints = apiEndPoints diff --git a/cmd/server-main_test.go b/cmd/server-main_test.go index df152b3ae..5fbc17029 100644 --- a/cmd/server-main_test.go +++ b/cmd/server-main_test.go @@ -19,7 +19,6 @@ package cmd import ( "errors" "flag" - "net/http" "os" "reflect" "runtime" @@ -120,9 +119,7 @@ func TestFinalizeAPIEndpoints(t *testing.T) { } for i, test := range testCases { - endPoints, err := finalizeAPIEndpoints(&http.Server{ - Addr: test.addr, - }) + endPoints, err := finalizeAPIEndpoints(test.addr) if err != nil && len(endPoints) <= 0 { t.Errorf("Test case %d returned with no API end points for %s", i+1, test.addr) diff --git a/cmd/server-mux.go b/cmd/server-mux.go index 16d525d28..ae2eb0b73 100644 --- a/cmd/server-mux.go +++ b/cmd/server-mux.go @@ -309,32 +309,28 @@ func (l *ListenerMux) Accept() (net.Conn, error) { // ServerMux - the main mux server type ServerMux struct { - *http.Server - listeners []*ListenerMux - WaitGroup *sync.WaitGroup - GracefulTimeout time.Duration - mu sync.Mutex // guards closed, conns, and listener - closed bool - conns map[net.Conn]http.ConnState // except terminal states + Addr string + handler http.Handler + listeners []*ListenerMux + + gracefulWait *sync.WaitGroup + gracefulTimeout time.Duration + + mu sync.Mutex // guards closed, and listener + closed bool } // NewServerMux constructor to create a ServerMux func NewServerMux(addr string, handler http.Handler) *ServerMux { m := &ServerMux{ - Server: &http.Server{ - Addr: addr, - Handler: handler, - MaxHeaderBytes: 1 << 20, - }, - WaitGroup: &sync.WaitGroup{}, + Addr: addr, + handler: handler, // Wait for 5 seconds for new incoming connnections, otherwise // forcibly close them during graceful stop or restart. - GracefulTimeout: 5 * time.Second, + gracefulTimeout: 5 * time.Second, + gracefulWait: &sync.WaitGroup{}, } - // Track connection state - m.connState() - // Returns configured HTTP server. return m } @@ -421,7 +417,7 @@ func (m *ServerMux) ListenAndServe(certFile, keyFile string) (err error) { go m.handleServiceSignals() - listeners, err := initListeners(m.Server.Addr, config) + listeners, err := initListeners(m.Addr, config) if err != nil { return err } @@ -445,8 +441,11 @@ func (m *ServerMux) ListenAndServe(certFile, keyFile string) (err error) { } http.Redirect(w, r, u.String(), http.StatusTemporaryRedirect) } else { - // Execute registered handlers - m.Server.Handler.ServeHTTP(w, r) + // Execute registered handlers, protect with a waitgroup + // to accomplish a graceful shutdown when the user asks to quit + m.gracefulWait.Add(1) + m.handler.ServeHTTP(w, r) + m.gracefulWait.Done() } }) @@ -470,6 +469,7 @@ func (m *ServerMux) ListenAndServe(certFile, keyFile string) (err error) { // Close initiates the graceful shutdown func (m *ServerMux) Close() error { m.mu.Lock() + if m.closed { m.mu.Unlock() return errors.New("Server has been closed") @@ -484,76 +484,21 @@ func (m *ServerMux) Close() error { return err } } - - m.SetKeepAlivesEnabled(false) - // Force close any idle and new connections. Waiting for other connections - // to close on their own (within the timeout period) - for c, st := range m.conns { - if st == http.StateIdle || st == http.StateNew { - c.Close() - } - } - - // If the GracefulTimeout happens then forcefully close all connections - t := time.AfterFunc(m.GracefulTimeout, func() { - for c := range m.conns { - c.Close() - } - }) - - // Wait for graceful timeout of connections. - defer t.Stop() - m.mu.Unlock() - // Block until all connections are closed - m.WaitGroup.Wait() + // Prepare for a graceful shutdown + waitSignal := make(chan struct{}) + go func() { + defer close(waitSignal) + m.gracefulWait.Wait() + }() + + select { + // Wait for everything to be properly closed + case <-waitSignal: + // Forced shutdown + case <-time.After(m.gracefulTimeout): + } return nil } - -// connState setups the ConnState tracking hook to know which connections are idle -func (m *ServerMux) connState() { - // Set our ConnState to track idle connections - m.Server.ConnState = func(c net.Conn, cs http.ConnState) { - m.mu.Lock() - defer m.mu.Unlock() - - switch cs { - case http.StateNew: - // New connections increment the WaitGroup and are added the the conns dictionary - m.WaitGroup.Add(1) - if m.conns == nil { - m.conns = make(map[net.Conn]http.ConnState) - } - m.conns[c] = cs - case http.StateActive: - // Only update status to StateActive if it's in the conns dictionary - if _, ok := m.conns[c]; ok { - m.conns[c] = cs - } - case http.StateIdle: - // Only update status to StateIdle if it's in the conns dictionary - if _, ok := m.conns[c]; ok { - m.conns[c] = cs - } - - // If we've already closed then we need to close this connection. - // We don't allow connections to become idle after server is closed - if m.closed { - c.Close() - } - case http.StateHijacked, http.StateClosed: - // If the connection is hijacked or closed we forget it - m.forgetConn(c) - } - } -} - -// forgetConn removes c from conns and decrements WaitGroup -func (m *ServerMux) forgetConn(c net.Conn) { - if _, ok := m.conns[c]; ok { - delete(m.conns, c) - m.WaitGroup.Done() - } -} diff --git a/cmd/server-mux_test.go b/cmd/server-mux_test.go index 661ad05a4..1a24473a6 100644 --- a/cmd/server-mux_test.go +++ b/cmd/server-mux_test.go @@ -29,7 +29,6 @@ import ( "math/big" "net" "net/http" - "net/http/httptest" "os" "runtime" "sync" @@ -181,113 +180,111 @@ func TestClose(t *testing.T) { } func TestServerMux(t *testing.T) { - ts := httptest.NewUnstartedServer(nil) - defer ts.Close() + var err error + var got []byte + var res *http.Response // Create ServerMux - m := NewServerMux("", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + m := NewServerMux("127.0.0.1:0", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "hello") })) + // Start serving requests + go m.ListenAndServe("", "") - // Set the test server config to the mux - ts.Config = m.Server - ts.Start() - - // Create a ListenerMux - lm := &ListenerMux{ - Listener: ts.Listener, - config: &tls.Config{}, - cond: sync.NewCond(&sync.Mutex{}), + // Issue a GET request. Since we started server in a goroutine, it could be not ready + // at this point. So we allow until 5 failed retries before declare there is an error + for i := 0; i < 5; i++ { + // Sleep one second + time.Sleep(1 * time.Second) + // Check if one listener is ready + m.mu.Lock() + if len(m.listeners) == 0 { + m.mu.Unlock() + continue + } + m.mu.Unlock() + // Issue the GET request + client := http.Client{} + m.mu.Lock() + res, err = client.Get("http://" + m.listeners[0].Addr().String()) + m.mu.Unlock() + if err != nil { + continue + } + // Read the request response + got, err = ioutil.ReadAll(res.Body) } - m.listeners = []*ListenerMux{lm} - client := http.Client{} - res, err := client.Get(ts.URL) - if err != nil { - t.Fatal(err) - } - - got, err := ioutil.ReadAll(res.Body) + // Check for error persisted after 5 times if err != nil { t.Fatal(err) } + // Check the web service response if string(got) != "hello" { t.Errorf("got %q, want hello", string(got)) } - - // Make sure there is only 1 connection - m.mu.Lock() - if len(m.conns) < 1 { - t.Fatal("Should have 1 connections") - } - m.mu.Unlock() - - // Close the server - m.Close() - - // Make sure there are zero connections - m.mu.Lock() - if len(m.conns) > 0 { - t.Fatal("Should have 0 connections") - } - m.mu.Unlock() } func TestServerCloseBlocking(t *testing.T) { - ts := httptest.NewUnstartedServer(nil) - defer ts.Close() - // Create ServerMux - m := NewServerMux("", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + m := NewServerMux("127.0.0.1:0", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "hello") })) - // Set the test server config to the mux - ts.Config = m.Server - ts.Start() + // Start serving requests in a goroutine + go m.ListenAndServe("", "") - // Create a ListenerMux. - lm := &ListenerMux{ - Listener: ts.Listener, - config: &tls.Config{}, - cond: sync.NewCond(&sync.Mutex{}), - } - m.listeners = []*ListenerMux{lm} - - dial := func() net.Conn { - c, cerr := net.Dial("tcp", ts.Listener.Addr().String()) - if cerr != nil { - t.Fatal(cerr) + // Dial, try until 5 times before declaring a failure + dial := func() (net.Conn, error) { + var c net.Conn + var err error + for i := 0; i < 5; i++ { + // Sleep one second in case of the server is not ready yet + time.Sleep(1 * time.Second) + // Check if there is at least one listener configured + m.mu.Lock() + if len(m.listeners) == 0 { + m.mu.Unlock() + continue + } + m.mu.Unlock() + // Run the actual Dial + m.mu.Lock() + c, err = net.Dial("tcp", m.listeners[0].Addr().String()) + m.mu.Unlock() + if err != nil { + continue + } } - return c + return c, err } // Dial to open a StateNew but don't send anything - cnew := dial() + cnew, err := dial() + if err != nil { + t.Fatal(err) + } defer cnew.Close() // Dial another connection but idle after a request to have StateIdle - cidle := dial() + cidle, err := dial() + if err != nil { + t.Fatal(err) + } defer cidle.Close() + cidle.Write([]byte("HEAD / HTTP/1.1\r\nHost: foo\r\n\r\n")) - _, err := http.ReadResponse(bufio.NewReader(cidle), nil) + _, err = http.ReadResponse(bufio.NewReader(cidle), nil) if err != nil { t.Fatal(err) } // Make sure we don't block forever. m.Close() - - // Make sure there are zero connections - m.mu.Lock() - if len(m.conns) > 0 { - t.Fatal("Should have 0 connections") - } - m.mu.Unlock() } -func TestListenAndServePlain(t *testing.T) { +func TestServerListenAndServePlain(t *testing.T) { wait := make(chan struct{}) addr := net.JoinHostPort("127.0.0.1", getFreePort()) errc := make(chan error) @@ -295,8 +292,6 @@ func TestListenAndServePlain(t *testing.T) { // Initialize done channel specifically for each tests. globalServiceDoneCh = make(chan struct{}, 1) - // Initialize signal channel specifically for each tests. - globalServiceSignalCh = make(chan serviceSignal, 1) // Create ServerMux and when we receive a request we stop waiting m := NewServerMux(addr, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -337,7 +332,7 @@ func TestListenAndServePlain(t *testing.T) { } } -func TestListenAndServeTLS(t *testing.T) { +func TestServerListenAndServeTLS(t *testing.T) { wait := make(chan struct{}) addr := net.JoinHostPort("127.0.0.1", getFreePort()) errc := make(chan error) diff --git a/cmd/server-startup-utils.go b/cmd/server-startup-utils.go index aef08e2b6..f19164595 100644 --- a/cmd/server-startup-utils.go +++ b/cmd/server-startup-utils.go @@ -19,7 +19,6 @@ package cmd import ( "fmt" "net" - "net/http" ) // getListenIPs - gets all the ips to listen on. @@ -49,7 +48,7 @@ func getListenIPs(serverAddr string) (hosts []string, port string, err error) { } // Finalizes the API endpoints based on the host list and port. -func finalizeAPIEndpoints(apiServer *http.Server) (endPoints []string, err error) { +func finalizeAPIEndpoints(addr string) (endPoints []string, err error) { // Verify current scheme. scheme := httpScheme if globalIsSSL { @@ -57,7 +56,7 @@ func finalizeAPIEndpoints(apiServer *http.Server) (endPoints []string, err error } // Get list of listen ips and port. - hosts, port, err1 := getListenIPs(apiServer.Addr) + hosts, port, err1 := getListenIPs(addr) if err1 != nil { return nil, err1 } From 533338bdebd1ca082793684ea418b9d23738dcf4 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 3 Feb 2017 23:27:50 -0800 Subject: [PATCH 42/75] all/windows: Be case in-sensitive about pattern matching. (#3682) Resource strings and paths are case insensitive on windows deployments but if user happens to use upper case instead of lower case for certain configuration params like bucket policies and bucket notification config. We might not honor them which leads to a wrong behavior on windows. This is windows only behavior, for all other platforms case is still kept sensitive. --- cmd/bucket-handlers-listobjects.go | 3 +-- cmd/bucket-handlers.go | 2 +- cmd/bucket-policy-handlers.go | 6 +++++ cmd/bucket-policy-parser.go | 6 ++--- cmd/generic-handlers.go | 4 ++-- cmd/lockinfo-handlers.go | 7 ++---- cmd/notifiers.go | 5 ++-- cmd/object-api-input-checks.go | 10 +++----- cmd/object-api-utils.go | 25 ++++++++++++++++++-- cmd/posix-list-dir-nix.go | 4 ---- cmd/posix-list-dir-others.go | 4 ---- cmd/posix-list-dir_test.go | 22 ------------------ cmd/posix-utils_common.go | 37 ------------------------------ cmd/tree-walk.go | 8 +++---- cmd/tree-walk_test.go | 2 +- 15 files changed, 48 insertions(+), 97 deletions(-) delete mode 100644 cmd/posix-utils_common.go diff --git a/cmd/bucket-handlers-listobjects.go b/cmd/bucket-handlers-listobjects.go index 81db8b65c..6381ce837 100644 --- a/cmd/bucket-handlers-listobjects.go +++ b/cmd/bucket-handlers-listobjects.go @@ -18,7 +18,6 @@ package cmd import ( "net/http" - "strings" "github.com/gorilla/mux" ) @@ -44,7 +43,7 @@ func validateListObjectsArgs(prefix, marker, delimiter string, maxKeys int) APIE // Marker is set validate pre-condition. if marker != "" { // Marker not common with prefix is not implemented. - if !strings.HasPrefix(marker, prefix) { + if !hasPrefix(marker, prefix) { return ErrNotImplemented } } diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index e6f5c6871..660396a3a 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -165,7 +165,7 @@ func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter, } if keyMarker != "" { // Marker not common with prefix is not implemented. - if !strings.HasPrefix(keyMarker, prefix) { + if !hasPrefix(keyMarker, prefix) { writeErrorResponse(w, ErrNotImplemented, r.URL) return } diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index 00b3b5d2b..d68e2537f 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -21,6 +21,8 @@ import ( "io" "io/ioutil" "net/http" + "runtime" + "strings" humanize "github.com/dustin/go-humanize" mux "github.com/gorilla/mux" @@ -63,6 +65,10 @@ func bucketPolicyActionMatch(action string, statement policyStatement) bool { // Match function matches wild cards in 'pattern' for resource. func resourceMatch(pattern, resource string) bool { + if runtime.GOOS == "windows" { + // For windows specifically make sure we are case insensitive. + return wildcard.Match(strings.ToLower(pattern), strings.ToLower(resource)) + } return wildcard.Match(pattern, resource) } diff --git a/cmd/bucket-policy-parser.go b/cmd/bucket-policy-parser.go index 7af5e5bf4..5d98b8690 100644 --- a/cmd/bucket-policy-parser.go +++ b/cmd/bucket-policy-parser.go @@ -111,12 +111,12 @@ func isValidResources(resources set.StringSet) (err error) { return err } for resource := range resources { - if !strings.HasPrefix(resource, bucketARNPrefix) { + if !hasPrefix(resource, bucketARNPrefix) { err = errors.New("Unsupported resource style found: ‘" + resource + "’, please validate your policy document") return err } resourceSuffix := strings.SplitAfter(resource, bucketARNPrefix)[1] - if len(resourceSuffix) == 0 || strings.HasPrefix(resourceSuffix, "/") { + if len(resourceSuffix) == 0 || hasPrefix(resourceSuffix, "/") { err = errors.New("Invalid resource style found: ‘" + resource + "’, please validate your policy document") return err } @@ -282,7 +282,7 @@ func checkBucketPolicyResources(bucket string, bucketPolicy *bucketPolicy) APIEr // nesting. Reject such rules. for _, otherResource := range resources { // Common prefix reject such rules. - if strings.HasPrefix(otherResource, resource) { + if hasPrefix(otherResource, resource) { return ErrPolicyNesting } } diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index 974045687..229e752b4 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -141,8 +141,8 @@ func setBrowserCacheControlHandler(h http.Handler) http.Handler { func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method == httpGET && guessIsBrowserReq(r) && globalIsBrowserEnabled { // For all browser requests set appropriate Cache-Control policies - if strings.HasPrefix(r.URL.Path, reservedBucket+"/") { - if strings.HasSuffix(r.URL.Path, ".js") || r.URL.Path == reservedBucket+"/favicon.ico" { + if hasPrefix(r.URL.Path, reservedBucket+"/") { + if hasSuffix(r.URL.Path, ".js") || r.URL.Path == reservedBucket+"/favicon.ico" { // For assets set cache expiry of one year. For each release, the name // of the asset name will change and hence it can not be served from cache. w.Header().Set("Cache-Control", "max-age=31536000") diff --git a/cmd/lockinfo-handlers.go b/cmd/lockinfo-handlers.go index 3a9e093f9..aa3fb234d 100644 --- a/cmd/lockinfo-handlers.go +++ b/cmd/lockinfo-handlers.go @@ -16,10 +16,7 @@ package cmd -import ( - "strings" - "time" -) +import "time" // SystemLockState - Structure to fill the lock state of entire object storage. // That is the total locks held, total calls blocked on locks and state of all the locks for the entire system. @@ -82,7 +79,7 @@ func listLocksInfo(bucket, prefix string, duration time.Duration) []VolumeLockIn continue } // N B empty prefix matches all param.path. - if !strings.HasPrefix(param.path, prefix) { + if !hasPrefix(param.path, prefix) { continue } diff --git a/cmd/notifiers.go b/cmd/notifiers.go index b7b5ec496..f1f1c4cbc 100644 --- a/cmd/notifiers.go +++ b/cmd/notifiers.go @@ -18,7 +18,6 @@ package cmd import ( "errors" - "strings" "github.com/minio/minio/pkg/wildcard" ) @@ -206,9 +205,9 @@ func filterRuleMatch(object string, frs []filterRule) bool { var prefixMatch, suffixMatch = true, true for _, fr := range frs { if isValidFilterNamePrefix(fr.Name) { - prefixMatch = strings.HasPrefix(object, fr.Value) + prefixMatch = hasPrefix(object, fr.Value) } else if isValidFilterNameSuffix(fr.Name) { - suffixMatch = strings.HasSuffix(object, fr.Value) + suffixMatch = hasSuffix(object, fr.Value) } } return prefixMatch && suffixMatch diff --git a/cmd/object-api-input-checks.go b/cmd/object-api-input-checks.go index 74b736e54..62e77ab16 100644 --- a/cmd/object-api-input-checks.go +++ b/cmd/object-api-input-checks.go @@ -16,11 +16,7 @@ package cmd -import ( - "strings" - - "github.com/skyrings/skyring-common/tools/uuid" -) +import "github.com/skyrings/skyring-common/tools/uuid" // Checks on GetObject arguments, bucket and object. func checkGetObjArgs(bucket, object string) error { @@ -69,7 +65,7 @@ func checkListObjsArgs(bucket, prefix, marker, delimiter string, obj ObjectLayer }) } // Verify if marker has prefix. - if marker != "" && !strings.HasPrefix(marker, prefix) { + if marker != "" && !hasPrefix(marker, prefix) { return traceError(InvalidMarkerPrefixCombination{ Marker: marker, Prefix: prefix, @@ -84,7 +80,7 @@ func checkListMultipartArgs(bucket, prefix, keyMarker, uploadIDMarker, delimiter return err } if uploadIDMarker != "" { - if strings.HasSuffix(keyMarker, slashSeparator) { + if hasSuffix(keyMarker, slashSeparator) { return traceError(InvalidUploadIDKeyCombination{ UploadIDMarker: uploadIDMarker, KeyMarker: keyMarker, diff --git a/cmd/object-api-utils.go b/cmd/object-api-utils.go index 95f63d339..206c0c1a0 100644 --- a/cmd/object-api-utils.go +++ b/cmd/object-api-utils.go @@ -22,6 +22,7 @@ import ( "io" "path" "regexp" + "runtime" "strings" "unicode/utf8" @@ -91,10 +92,10 @@ func IsValidObjectName(object string) bool { if len(object) == 0 { return false } - if strings.HasSuffix(object, slashSeparator) { + if hasSuffix(object, slashSeparator) { return false } - if strings.HasPrefix(object, slashSeparator) { + if hasPrefix(object, slashSeparator) { return false } return IsValidObjectPrefix(object) @@ -159,6 +160,26 @@ func getCompleteMultipartMD5(parts []completePart) (string, error) { return s3MD5, nil } +// Prefix matcher string matches prefix in a platform specific way. +// For example on windows since its case insensitive we are supposed +// to do case insensitive checks. +func hasPrefix(s string, prefix string) bool { + if runtime.GOOS == "windows" { + return strings.HasPrefix(strings.ToLower(s), strings.ToLower(prefix)) + } + return strings.HasPrefix(s, prefix) +} + +// Suffix matcher string matches suffix in a platform specific way. +// For example on windows since its case insensitive we are supposed +// to do case insensitive checks. +func hasSuffix(s string, suffix string) bool { + if runtime.GOOS == "windows" { + return strings.HasSuffix(strings.ToLower(s), strings.ToLower(suffix)) + } + return strings.HasSuffix(s, suffix) +} + // byBucketName is a collection satisfying sort.Interface. type byBucketName []BucketInfo diff --git a/cmd/posix-list-dir-nix.go b/cmd/posix-list-dir-nix.go index 62421abce..1da7eaf76 100644 --- a/cmd/posix-list-dir-nix.go +++ b/cmd/posix-list-dir-nix.go @@ -68,10 +68,6 @@ func parseDirents(dirPath string, buf []byte) (entries []string, err error) { if name == "." || name == ".." { continue } - // Skip special files. - if hasPosixReservedPrefix(name) { - continue - } switch dirent.Type { case syscall.DT_DIR: diff --git a/cmd/posix-list-dir-others.go b/cmd/posix-list-dir-others.go index abd3d965b..dd40faca5 100644 --- a/cmd/posix-list-dir-others.go +++ b/cmd/posix-list-dir-others.go @@ -52,10 +52,6 @@ func readDir(dirPath string) (entries []string, err error) { return nil, err } for _, fi := range fis { - // Skip special files, if found. - if hasPosixReservedPrefix(fi.Name()) { - continue - } // Stat symbolic link and follow to get the final value. if fi.Mode()&os.ModeSymlink == os.ModeSymlink { var st os.FileInfo diff --git a/cmd/posix-list-dir_test.go b/cmd/posix-list-dir_test.go index c709f7ec5..30d85b862 100644 --- a/cmd/posix-list-dir_test.go +++ b/cmd/posix-list-dir_test.go @@ -69,26 +69,6 @@ func setupTestReadDirEmpty(t *testing.T) (testResults []result) { return testResults } -// Test to read empty directory with only reserved names. -func setupTestReadDirReserved(t *testing.T) (testResults []result) { - dir := mustSetupDir(t) - entries := []string{} - // Create a file with reserved name. - for _, reservedName := range posixReservedPrefix { - if err := ioutil.WriteFile(filepath.Join(dir, reservedName), []byte{}, os.ModePerm); err != nil { - // For cleanup, its required to add these entries into test results. - testResults = append(testResults, result{dir, entries}) - t.Fatalf("Unable to create file, %s", err) - } - // entries = append(entries, reservedName) - reserved files are skipped. - } - sort.Strings(entries) - - // Add entries slice for this test directory. - testResults = append(testResults, result{dir, entries}) - return testResults -} - // Test to read non-empty directory with only files. func setupTestReadDirFiles(t *testing.T) (testResults []result) { dir := mustSetupDir(t) @@ -198,8 +178,6 @@ func TestReadDir(t *testing.T) { // Setup and capture test results for empty directory. testResults = append(testResults, setupTestReadDirEmpty(t)...) - // Setup and capture test results for reserved files. - testResults = append(testResults, setupTestReadDirReserved(t)...) // Setup and capture test results for directory with only files. testResults = append(testResults, setupTestReadDirFiles(t)...) // Setup and capture test results for directory with files and directories. diff --git a/cmd/posix-utils_common.go b/cmd/posix-utils_common.go deleted file mode 100644 index ea15b8bca..000000000 --- a/cmd/posix-utils_common.go +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2016 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 cmd - -import "strings" - -// List of reserved words for files, includes old and new ones. -var posixReservedPrefix = []string{ - "$tmpfile", - // Add new reserved words if any used in future. -} - -// hasPosixReservedPrefix - has reserved prefix. -func hasPosixReservedPrefix(name string) (isReserved bool) { - for _, reservedKey := range posixReservedPrefix { - if strings.HasPrefix(name, reservedKey) { - isReserved = true - break - } - } - - return isReserved -} diff --git a/cmd/tree-walk.go b/cmd/tree-walk.go index 8993a96d0..05c78b0cd 100644 --- a/cmd/tree-walk.go +++ b/cmd/tree-walk.go @@ -67,7 +67,7 @@ func filterMatchingPrefix(entries []string, prefixEntry string) []string { if start == end { break } - if strings.HasPrefix(entries[start], prefixEntry) { + if hasPrefix(entries[start], prefixEntry) { break } start++ @@ -76,7 +76,7 @@ func filterMatchingPrefix(entries []string, prefixEntry string) []string { if start == end { break } - if strings.HasPrefix(entries[end-1], prefixEntry) { + if hasPrefix(entries[end-1], prefixEntry) { break } end-- @@ -173,7 +173,7 @@ func doTreeWalk(bucket, prefixDir, entryPrefixMatch, marker string, recursive bo // Skip as the marker would already be listed in the previous listing. continue } - if recursive && !strings.HasSuffix(entry, slashSeparator) { + if recursive && !hasSuffix(entry, slashSeparator) { // We should not skip for recursive listing and if markerDir is a directory // for ex. if marker is "four/five.txt" markerDir will be "four/" which // should not be skipped, instead it will need to be treeWalk()'ed into. @@ -182,7 +182,7 @@ func doTreeWalk(bucket, prefixDir, entryPrefixMatch, marker string, recursive bo continue } } - if recursive && strings.HasSuffix(entry, slashSeparator) { + if recursive && hasSuffix(entry, slashSeparator) { // If the entry is a directory, we will need recurse into it. markerArg := "" if entry == markerDir { diff --git a/cmd/tree-walk_test.go b/cmd/tree-walk_test.go index 939439f2f..9490c6c56 100644 --- a/cmd/tree-walk_test.go +++ b/cmd/tree-walk_test.go @@ -135,7 +135,7 @@ func testTreeWalkPrefix(t *testing.T, listDir listDirFunc, isLeaf isLeafFunc) { // Check if all entries received on the channel match the prefix. for res := range twResultCh { - if !strings.HasPrefix(res.entry, prefix) { + if !hasPrefix(res.entry, prefix) { t.Errorf("Entry %s doesn't match prefix %s", res.entry, prefix) } } From 6717a0b68c164926c13a7d0c540c59fdc51f33d8 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sun, 5 Feb 2017 18:31:48 -0800 Subject: [PATCH 43/75] Add consistency guarantees --- docs/distributed/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/distributed/README.md b/docs/distributed/README.md index a76002f24..2b5189be3 100644 --- a/docs/distributed/README.md +++ b/docs/distributed/README.md @@ -22,6 +22,10 @@ As with Minio in stand-alone mode, distributed Minio has a per tenant limit of m Note that with distributed Minio you can play around with the number of nodes and drives as long as the limits are adhered to. For example, you can have 2 nodes with 4 drives each, 4 nodes with 4 drives each, 8 nodes with 2 drives each, and so on. +### Consistency Guarantees + +Minio follows strict **read-after-write** consistency model for all i/o operations both in distributed and standalone modes. + # Get started If you're aware of stand-alone Minio set up, the process remains largely the same, as the Minio server automatically switches to stand-alone or distributed mode, depending on the command line parameters. From 93fd2693295c0cfeb875bfa5c283651c7a4d1cb2 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Mon, 6 Feb 2017 18:29:53 +0100 Subject: [PATCH 44/75] stats: Add network and http statisics (#3686) Network: total bytes of incoming and outgoing server's data by taking advantage of our ConnMux Read/Write wrapping HTTP: total number of different http verbs passed in http requests and different status codes passed in http responses. This is counted in a new http handler. --- cmd/generic-handlers.go | 49 +++++++++++++++ cmd/globals.go | 5 ++ cmd/routers.go | 2 + cmd/server-mux.go | 35 +++++++---- cmd/stats.go | 129 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 cmd/stats.go diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index 229e752b4..b118f1725 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -356,3 +356,52 @@ func (h resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Serve HTTP. h.handler.ServeHTTP(w, r) } + +// httpResponseRecorder wraps http.ResponseWriter +// to record some useful http response data. +type httpResponseRecorder struct { + http.ResponseWriter + http.Flusher + respStatusCode int +} + +// Wraps ResponseWriter's Write() +func (rww *httpResponseRecorder) Write(b []byte) (int, error) { + return rww.ResponseWriter.Write(b) +} + +// Wraps ResponseWriter's Flush() +func (rww *httpResponseRecorder) Flush() { + f, ok := rww.ResponseWriter.(http.Flusher) + if ok { + f.Flush() + } +} + +// Wraps ResponseWriter's WriteHeader() and record +// the response status code +func (rww *httpResponseRecorder) WriteHeader(httpCode int) { + rww.respStatusCode = httpCode + rww.ResponseWriter.WriteHeader(httpCode) +} + +// httpStatsHandler definition: gather HTTP statistics +type httpStatsHandler struct { + handler http.Handler +} + +// setHttpStatsHandler sets a http Stats Handler +func setHTTPStatsHandler(h http.Handler) http.Handler { + return httpStatsHandler{handler: h} +} + +func (h httpStatsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Wraps w to record http response information + ww := &httpResponseRecorder{ResponseWriter: w} + + // Execute the request + h.handler.ServeHTTP(ww, r) + + // Update http statistics + globalHTTPStats.updateStats(r, ww) +} diff --git a/cmd/globals.go b/cmd/globals.go index be77a78db..8b9f312cb 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -122,6 +122,11 @@ var ( // url.URL endpoints of disks that belong to the object storage. globalEndpoints = []*url.URL{} + // Global server's network statistics + globalConnStats = newConnStats() + // Global HTTP request statisitics + globalHTTPStats = newHTTPStats() + // Add new variable global values here. ) diff --git a/cmd/routers.go b/cmd/routers.go index dfee5e590..9213f65be 100644 --- a/cmd/routers.go +++ b/cmd/routers.go @@ -84,6 +84,8 @@ func configureServerHandler(srvCmdConfig serverCmdConfig) (http.Handler, error) // List of some generic handlers which are applied for all incoming requests. var handlerFns = []HandlerFunc{ + // Network statistics + setHTTPStatsHandler, // Limits all requests size to a maximum fixed limit setRequestSizeLimitHandler, // Adds 'crossdomain.xml' policy handler to serve legacy flash clients. diff --git a/cmd/server-mux.go b/cmd/server-mux.go index ae2eb0b73..8ea33a3d5 100644 --- a/cmd/server-mux.go +++ b/cmd/server-mux.go @@ -58,16 +58,16 @@ var defaultHTTP1Methods = []string{ // connections on the same listeners. type ConnMux struct { net.Conn - bufrw *bufio.ReadWriter + // To peek net.Conn incoming data + peeker *bufio.Reader } // NewConnMux - creates a new ConnMux instance func NewConnMux(c net.Conn) *ConnMux { br := bufio.NewReader(c) - bw := bufio.NewWriter(c) return &ConnMux{ - Conn: c, - bufrw: bufio.NewReadWriter(br, bw), + Conn: c, + peeker: bufio.NewReader(br), } } @@ -83,7 +83,7 @@ const ( // errors in peeking over the connection. func (c *ConnMux) PeekProtocol() (string, error) { // Peek for HTTP verbs. - buf, err := c.bufrw.Peek(maxHTTPVerbLen) + buf, err := c.peeker.Peek(maxHTTPVerbLen) if err != nil { return "", err } @@ -110,20 +110,31 @@ func (c *ConnMux) PeekProtocol() (string, error) { // Read - streams the ConnMux buffer when reset flag is activated, otherwise // streams from the incoming network connection -func (c *ConnMux) Read(b []byte) (int, error) { +func (c *ConnMux) Read(b []byte) (n int, e error) { // Push read deadline c.Conn.SetReadDeadline(time.Now().Add(defaultTCPReadTimeout)) - return c.bufrw.Read(b) + + // Update server's connection statistics + defer func() { + globalConnStats.incInputBytes(n) + }() + + return c.peeker.Read(b) +} + +func (c *ConnMux) Write(b []byte) (n int, e error) { + // Update server's connection statistics + defer func() { + globalConnStats.incOutputBytes(n) + }() + // Run the underlying net.Conn Write() func + return c.Conn.Write(b) } // Close the connection. func (c *ConnMux) Close() (err error) { // Make sure that we always close a connection, - // even if the bufioWriter flush sends an error. - defer c.Conn.Close() - - // Flush and write to the connection. - return c.bufrw.Flush() + return c.Conn.Close() } // ListenerMux wraps the standard net.Listener to inspect diff --git a/cmd/stats.go b/cmd/stats.go new file mode 100644 index 000000000..9dc691839 --- /dev/null +++ b/cmd/stats.go @@ -0,0 +1,129 @@ +/* + * Minio Cloud Storage, (C) 2017 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 cmd + +import ( + "net/http" + "sync/atomic" +) + +// counter - simplify atomic counting +type counter struct { + val uint64 +} + +// Inc increases counter atomically +func (c *counter) Inc(n uint64) { + atomic.AddUint64(&c.val, n) +} + +// Value fetches counter's value atomically +func (c *counter) Value() uint64 { + return atomic.LoadUint64(&c.val) +} + +// ConnStats - Network statistics +// Count total input/output transferred bytes during +// the server's life. +type ConnStats struct { + totalInputBytes counter + totalOutputBytes counter +} + +// Increase total input bytes +func (s *ConnStats) incInputBytes(n int) { + s.totalInputBytes.Inc(uint64(n)) +} + +// Increase total output bytes +func (s *ConnStats) incOutputBytes(n int) { + s.totalOutputBytes.Inc(uint64(n)) +} + +// Return total input bytes +func (s *ConnStats) getTotalInputBytes() uint64 { + return s.totalInputBytes.Value() +} + +// Return total output bytes +func (s *ConnStats) getTotalOutputBytes() uint64 { + return s.totalOutputBytes.Value() +} + +// Prepare new ConnStats structure +func newConnStats() *ConnStats { + return &ConnStats{} +} + +// httpStats holds statistics information about +// HTTP requests made by all clients +type httpStats struct { + // HEAD request stats + totalHEADs counter + successHEADs counter + // GET request stats + totalGETs counter + successGETs counter + // PUT request + totalPUTs counter + successPUTs counter + // POST request + totalPOSTs counter + successPOSTs counter + // DELETE request + totalDELETEs counter + successDELETEs counter +} + +// Update statistics from http request and response data +func (st *httpStats) updateStats(r *http.Request, w *httpResponseRecorder) { + // A successful request has a 2xx response code + successReq := (w.respStatusCode >= 200 && w.respStatusCode < 300) + // Update stats according to method verb + switch r.Method { + case "HEAD": + st.totalHEADs.Inc(1) + if successReq { + st.successHEADs.Inc(1) + } + case "GET": + st.totalGETs.Inc(1) + if successReq { + st.successGETs.Inc(1) + } + case "PUT": + st.totalPUTs.Inc(1) + if successReq { + st.successPUTs.Inc(1) + } + case "POST": + st.totalPOSTs.Inc(1) + if successReq { + st.successPOSTs.Inc(1) + } + case "DELETE": + st.totalDELETEs.Inc(1) + if successReq { + st.successDELETEs.Inc(1) + } + } +} + +// Prepare new HttpStats structure +func newHTTPStats() *httpStats { + return &httpStats{} +} From 45d9cfa0c5da82109d490c20f1eb076addf47ce4 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Mon, 6 Feb 2017 13:09:09 -0800 Subject: [PATCH 45/75] signature-v4: stringToSign and signingKey should use Scope's date. (#3688) fixes #3676 --- cmd/signature-v4-parser.go | 10 ++++++++++ cmd/signature-v4.go | 20 +++++++------------- cmd/signature-v4_test.go | 11 ++--------- cmd/streaming-signature-v4.go | 4 ++-- cmd/test-utils_test.go | 5 +++-- cmd/web-handlers.go | 2 +- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/cmd/signature-v4-parser.go b/cmd/signature-v4-parser.go index 913099e47..475361fa4 100644 --- a/cmd/signature-v4-parser.go +++ b/cmd/signature-v4-parser.go @@ -34,6 +34,16 @@ type credentialHeader struct { } } +// Return scope string. +func (c credentialHeader) getScope() string { + return strings.Join([]string{ + c.scope.date.Format(yyyymmdd), + c.scope.region, + c.scope.service, + c.scope.request, + }, "/") +} + // parse credentialHeader string into its structured form. func parseCredentialHeader(credElement string) (credentialHeader, APIErrorCode) { creds := strings.Split(strings.TrimSpace(credElement), "=") diff --git a/cmd/signature-v4.go b/cmd/signature-v4.go index 174e7579d..f6a5ea2fb 100644 --- a/cmd/signature-v4.go +++ b/cmd/signature-v4.go @@ -124,9 +124,9 @@ func getScope(t time.Time, region string) string { } // getStringToSign a string based on selected query values. -func getStringToSign(canonicalRequest string, t time.Time, region string) string { +func getStringToSign(canonicalRequest string, t time.Time, scope string) string { stringToSign := signV4Algorithm + "\n" + t.Format(iso8601Format) + "\n" - stringToSign = stringToSign + getScope(t, region) + "\n" + stringToSign = stringToSign + scope + "\n" canonicalRequestBytes := sha256.Sum256([]byte(canonicalRequest)) stringToSign = stringToSign + hex.EncodeToString(canonicalRequestBytes[:]) return stringToSign @@ -182,14 +182,8 @@ func doesPolicySignatureV4Match(formValues map[string]string) APIErrorCode { return ErrInvalidRegion } - // Parse date string. - t, e := time.Parse(iso8601Format, formValues["X-Amz-Date"]) - if e != nil { - return ErrMalformedDate - } - // Get signing key. - signingKey := getSigningKey(cred.SecretKey, t, region) + signingKey := getSigningKey(cred.SecretKey, credHeader.scope.date, region) // Get signature. newSignature := getSignature(signingKey, formValues["Policy"]) @@ -311,10 +305,10 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s presignedCanonicalReq := getCanonicalRequest(extractedSignedHeaders, hashedPayload, encodedQuery, req.URL.Path, req.Method, req.Host) // Get string to sign from canonical request. - presignedStringToSign := getStringToSign(presignedCanonicalReq, t, region) + presignedStringToSign := getStringToSign(presignedCanonicalReq, t, pSignValues.Credential.getScope()) // Get hmac presigned signing key. - presignedSigningKey := getSigningKey(cred.SecretKey, t, region) + presignedSigningKey := getSigningKey(cred.SecretKey, pSignValues.Credential.scope.date, region) // Get new signature. newSignature := getSignature(presignedSigningKey, presignedStringToSign) @@ -408,10 +402,10 @@ func doesSignatureMatch(hashedPayload string, r *http.Request, region string) AP canonicalRequest := getCanonicalRequest(extractedSignedHeaders, hashedPayload, queryStr, req.URL.Path, req.Method, req.Host) // Get string to sign from canonical request. - stringToSign := getStringToSign(canonicalRequest, t, region) + stringToSign := getStringToSign(canonicalRequest, t, signV4Values.Credential.getScope()) // Get hmac signing key. - signingKey := getSigningKey(cred.SecretKey, t, region) + signingKey := getSigningKey(cred.SecretKey, signV4Values.Credential.scope.date, region) // Calculate signature. newSignature := getSignature(signingKey, stringToSign) diff --git a/cmd/signature-v4_test.go b/cmd/signature-v4_test.go index 4990f9941..12137d1e1 100644 --- a/cmd/signature-v4_test.go +++ b/cmd/signature-v4_test.go @@ -61,14 +61,7 @@ func TestDoesPolicySignatureMatch(t *testing.T) { }, expected: ErrInvalidRegion, }, - // (3) It should fail if the date is invalid (or missing, in this case). - { - form: map[string]string{ - "X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion), - }, - expected: ErrMalformedDate, - }, - // (4) It should fail with a bad signature. + // (3) It should fail with a bad signature. { form: map[string]string{ "X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion), @@ -78,7 +71,7 @@ func TestDoesPolicySignatureMatch(t *testing.T) { }, expected: ErrSignatureDoesNotMatch, }, - // (5) It should succeed if everything is correct. + // (4) It should succeed if everything is correct. { form: map[string]string{ "X-Amz-Credential": fmt.Sprintf(credentialTemplate, accessKey, now.Format(yyyymmdd), globalMinioDefaultRegion), diff --git a/cmd/streaming-signature-v4.go b/cmd/streaming-signature-v4.go index d2bbc3d66..8e703bfb4 100644 --- a/cmd/streaming-signature-v4.go +++ b/cmd/streaming-signature-v4.go @@ -135,10 +135,10 @@ func calculateSeedSignature(r *http.Request) (signature string, date time.Time, canonicalRequest := getCanonicalRequest(extractedSignedHeaders, payload, queryStr, req.URL.Path, req.Method, req.Host) // Get string to sign from canonical request. - stringToSign := getStringToSign(canonicalRequest, date, region) + stringToSign := getStringToSign(canonicalRequest, date, signV4Values.Credential.getScope()) // Get hmac signing key. - signingKey := getSigningKey(cred.SecretKey, date, region) + signingKey := getSigningKey(cred.SecretKey, signV4Values.Credential.scope.date, region) // Calculate signature. newSignature := getSignature(signingKey, stringToSign) diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 98c6bc15e..67219df0c 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -893,7 +893,8 @@ func preSignV4(req *http.Request, accessKeyID, secretAccessKey string, expires i region := serverConfig.GetRegion() date := time.Now().UTC() - credential := fmt.Sprintf("%s/%s", accessKeyID, getScope(date, region)) + scope := getScope(date, region) + credential := fmt.Sprintf("%s/%s", accessKeyID, scope) // Set URL query. query := req.URL.Query() @@ -909,7 +910,7 @@ func preSignV4(req *http.Request, accessKeyID, secretAccessKey string, expires i queryStr := strings.Replace(query.Encode(), "+", "%20", -1) canonicalRequest := getCanonicalRequest(extractedSignedHeaders, unsignedPayload, queryStr, req.URL.Path, req.Method, req.Host) - stringToSign := getStringToSign(canonicalRequest, date, region) + stringToSign := getStringToSign(canonicalRequest, date, scope) signingKey := getSigningKey(secretAccessKey, date, region) signature := getSignature(signingKey, stringToSign) diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 4943fa78c..d3f65a0e8 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -748,7 +748,7 @@ func presignedGet(host, bucket, object string, expiry int64) string { var extractedSignedHeaders http.Header canonicalRequest := getCanonicalRequest(extractedSignedHeaders, unsignedPayload, query, path, "GET", host) - stringToSign := getStringToSign(canonicalRequest, date, region) + stringToSign := getStringToSign(canonicalRequest, date, getScope(date, region)) signingKey := getSigningKey(secretKey, date, region) signature := getSignature(signingKey, stringToSign) From 70e70446bbb8c7273b9724f91303639d85040696 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Mon, 6 Feb 2017 23:19:27 +0100 Subject: [PATCH 46/75] signv4: Read always returns EOF when stream ends (#3692) When EOF is reached, further calls of Read() doesn't return io.EOF but continue to work as it expects to have more data, this PR fixes the behavior --- cmd/object-handlers_test.go | 32 +++++++++++++++++++++++--------- cmd/streaming-signature-v4.go | 11 +++++++++-- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/cmd/object-handlers_test.go b/cmd/object-handlers_test.go index 5d0359d0c..95e126202 100644 --- a/cmd/object-handlers_test.go +++ b/cmd/object-handlers_test.go @@ -489,6 +489,20 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam shouldPass: true, }, // Test case - 3 + // Empty data + { + bucketName: bucketName, + objectName: objectName, + data: []byte{}, + dataLen: 0, + chunkSize: 64 * humanize.KiByte, + expectedContent: []byte{}, + expectedRespStatus: http.StatusOK, + accessKey: credentials.AccessKey, + secretKey: credentials.SecretKey, + shouldPass: true, + }, + // Test case - 4 // Invalid access key id. { bucketName: bucketName, @@ -502,7 +516,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam secretKey: "", shouldPass: false, }, - // Test case - 4 + // Test case - 5 // Wrong auth header returns as bad request. { bucketName: bucketName, @@ -517,7 +531,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam shouldPass: false, removeAuthHeader: true, }, - // Test case - 5 + // Test case - 6 // Large chunk size.. also passes. { bucketName: bucketName, @@ -531,7 +545,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam secretKey: credentials.SecretKey, shouldPass: false, }, - // Test case - 6 + // Test case - 7 // Chunk with malformed encoding. { bucketName: bucketName, @@ -546,7 +560,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam shouldPass: false, fault: malformedEncoding, }, - // Test case - 7 + // Test case - 8 // Chunk with shorter than advertised chunk data. { bucketName: bucketName, @@ -561,7 +575,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam shouldPass: false, fault: unexpectedEOF, }, - // Test case - 8 + // Test case - 9 // Chunk with first chunk data byte tampered. { bucketName: bucketName, @@ -576,7 +590,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam shouldPass: false, fault: signatureMismatch, }, - // Test case - 9 + // Test case - 10 // Different date (timestamps) used in seed signature calculation // and chunks signature calculation. { @@ -592,7 +606,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam shouldPass: false, fault: chunkDateMismatch, }, - // Test case - 10 + // Test case - 11 // Set x-amz-decoded-content-length to a value too big to hold in int64. { bucketName: bucketName, @@ -669,11 +683,11 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam } buffer := new(bytes.Buffer) - err = obj.GetObject(testCase.bucketName, testCase.objectName, 0, int64(bytesDataLen), buffer) + err = obj.GetObject(testCase.bucketName, testCase.objectName, 0, int64(testCase.dataLen), buffer) if err != nil { t.Fatalf("Test %d: %s: Failed to fetch the copied object: %s", i+1, instanceType, err) } - if !bytes.Equal(bytesData, buffer.Bytes()) { + if !bytes.Equal(testCase.data, buffer.Bytes()) { t.Errorf("Test %d: %s: Data Mismatch: Data fetched back from the uploaded object doesn't match the original one.", i+1, instanceType) } buffer.Reset() diff --git a/cmd/streaming-signature-v4.go b/cmd/streaming-signature-v4.go index 8e703bfb4..9383c17a0 100644 --- a/cmd/streaming-signature-v4.go +++ b/cmd/streaming-signature-v4.go @@ -221,6 +221,7 @@ const ( readChunkTrailer readChunk verifyChunk + eofChunk ) func (cs chunkState) String() string { @@ -234,6 +235,9 @@ func (cs chunkState) String() string { stateString = "readChunk" case verifyChunk: stateString = "verifyChunk" + case eofChunk: + stateString = "eofChunk" + } return stateString } @@ -309,10 +313,13 @@ func (cr *s3ChunkedReader) Read(buf []byte) (n int, err error) { // this follows the chaining. cr.seedSignature = newSignature cr.chunkSHA256Writer.Reset() - cr.state = readChunkHeader if cr.lastChunk { - return n, nil + cr.state = eofChunk + } else { + cr.state = readChunkHeader } + case eofChunk: + return n, io.EOF } } } From a170e44689055b3d4bbb0450323018eff08623d3 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 6 Feb 2017 23:46:33 -0800 Subject: [PATCH 47/75] Let hijacker and flusher interfaces to be reflected. (#3709) Ideally here if the interface is not found it would fail the server, as it should be because without these we can't even have a working server in the first place. Just like how it fails in master invariably inside Go net/http code path. Fixes #3708 --- cmd/generic-handlers.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index b118f1725..0bf9fd9da 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -17,6 +17,8 @@ package cmd import ( + "bufio" + "net" "net/http" "path" "strings" @@ -361,7 +363,6 @@ func (h resourceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // to record some useful http response data. type httpResponseRecorder struct { http.ResponseWriter - http.Flusher respStatusCode int } @@ -372,10 +373,7 @@ func (rww *httpResponseRecorder) Write(b []byte) (int, error) { // Wraps ResponseWriter's Flush() func (rww *httpResponseRecorder) Flush() { - f, ok := rww.ResponseWriter.(http.Flusher) - if ok { - f.Flush() - } + rww.ResponseWriter.(http.Flusher).Flush() } // Wraps ResponseWriter's WriteHeader() and record @@ -385,6 +383,10 @@ func (rww *httpResponseRecorder) WriteHeader(httpCode int) { rww.ResponseWriter.WriteHeader(httpCode) } +func (rww *httpResponseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) { + return rww.ResponseWriter.(http.Hijacker).Hijack() +} + // httpStatsHandler definition: gather HTTP statistics type httpStatsHandler struct { handler http.Handler From 310bf5bd3690e0f65ac2f5c83730d5d1add9b8d0 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 7 Feb 2017 02:16:29 -0800 Subject: [PATCH 48/75] auth/rpc: Make auth rpc client retry configurable. (#3695) Currently the auth rpc client defaults to to a maximum cap of 30seconds timeout. Make this to be configurable by the caller of authRPCClient during initialization, if no such config is provided then default to 30 seconds. --- cmd/auth-rpc-client.go | 33 +++++++++++++++-- cmd/prepare-storage.go | 9 ++--- cmd/retry-storage.go | 5 ++- cmd/retry.go | 33 ++++++++++++++--- cmd/retry_test.go | 82 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 11 deletions(-) create mode 100644 cmd/retry_test.go diff --git a/cmd/auth-rpc-client.go b/cmd/auth-rpc-client.go index 0df2f5286..74c7815b6 100644 --- a/cmd/auth-rpc-client.go +++ b/cmd/auth-rpc-client.go @@ -35,6 +35,19 @@ type authConfig struct { secureConn bool // Make TLS connection to RPC server or not. serviceName string // Service name of auth server. disableReconnect bool // Disable reconnect on failure or not. + + /// Retry configurable values. + + // Each retry unit multiplicative, measured in time.Duration. + // This is the basic unit used for calculating backoffs. + retryUnit time.Duration + // Maximum retry duration i.e A caller would wait no more than this + // duration to continue their loop. + retryCap time.Duration + + // Maximum retries an call authRPC client would do for a failed + // RPC call. + retryAttemptThreshold int } // AuthRPCClient is a authenticated RPC client which does authentication before doing Call(). @@ -47,6 +60,18 @@ type AuthRPCClient struct { // newAuthRPCClient - returns a JWT based authenticated (go) rpc client, which does automatic reconnect. func newAuthRPCClient(config authConfig) *AuthRPCClient { + // Check if retry params are set properly if not default them. + emptyDuration := time.Duration(int64(0)) + if config.retryUnit == emptyDuration { + config.retryUnit = defaultRetryUnit + } + if config.retryCap == emptyDuration { + config.retryCap = defaultRetryCap + } + if config.retryAttemptThreshold == 0 { + config.retryAttemptThreshold = globalAuthRPCRetryThreshold + } + return &AuthRPCClient{ rpcClient: newRPCClient(config.serverAddr, config.serviceEndpoint, config.secureConn), config: config, @@ -105,9 +130,13 @@ func (authClient *AuthRPCClient) Call(serviceMethod string, args interface { SetAuthToken(authToken string) SetRequestTime(requestTime time.Time) }, reply interface{}) (err error) { + + // Done channel is used to close any lingering retry routine, as soon + // as this function returns. doneCh := make(chan struct{}) defer close(doneCh) - for i := range newRetryTimer(time.Second, 30*time.Second, MaxJitter, doneCh) { + + for i := range newRetryTimer(authClient.config.retryUnit, authClient.config.retryCap, doneCh) { if err = authClient.call(serviceMethod, args, reply); err == rpc.ErrShutdown { // As connection at server side is closed, close the rpc client. authClient.Close() @@ -115,7 +144,7 @@ func (authClient *AuthRPCClient) Call(serviceMethod string, args interface { // Retry if reconnect is not disabled. if !authClient.config.disableReconnect { // Retry until threshold reaches. - if i < globalAuthRPCRetryThreshold { + if i < authClient.config.retryAttemptThreshold { continue } } diff --git a/cmd/prepare-storage.go b/cmd/prepare-storage.go index 36bb20a1e..839474484 100644 --- a/cmd/prepare-storage.go +++ b/cmd/prepare-storage.go @@ -198,10 +198,11 @@ func retryFormattingXLDisks(firstDisk bool, endpoints []*url.URL, storageDisks [ return errInvalidArgument } - // Create a done channel to control 'ListObjects' go routine. - doneCh := make(chan struct{}, 1) + // Done channel is used to close any lingering retry routine, as soon + // as this function returns. + doneCh := make(chan struct{}) - // Indicate to our routine to exit cleanly upon return. + // Indicate to our retry routine to exit cleanly, upon this function return. defer close(doneCh) // prepare getElapsedTime() to calculate elapsed time since we started trying formatting disks. @@ -212,7 +213,7 @@ func retryFormattingXLDisks(firstDisk bool, endpoints []*url.URL, storageDisks [ } // Wait on the jitter retry loop. - retryTimerCh := newRetryTimer(time.Second, time.Second*30, MaxJitter, doneCh) + retryTimerCh := newRetryTimerSimple(doneCh) for { select { case retryCount := <-retryTimerCh: diff --git a/cmd/retry-storage.go b/cmd/retry-storage.go index 23a7526a3..f30170ed8 100644 --- a/cmd/retry-storage.go +++ b/cmd/retry-storage.go @@ -220,9 +220,12 @@ func (f retryStorage) reInit() (err error) { // Close the underlying connection. f.remoteStorage.Close() // Error here is purposefully ignored. + // Done channel is used to close any lingering retry routine, as soon + // as this function returns. doneCh := make(chan struct{}) defer close(doneCh) - for i := range newRetryTimer(f.retryUnit, f.retryCap, MaxJitter, doneCh) { + + for i := range newRetryTimer(f.retryUnit, f.retryCap, doneCh) { // Initialize and make a new login attempt. err = f.remoteStorage.Init() if err != nil { diff --git a/cmd/retry.go b/cmd/retry.go index 79d0b5f4d..5e42182c6 100644 --- a/cmd/retry.go +++ b/cmd/retry.go @@ -48,7 +48,8 @@ func (r *lockedRandSource) Seed(seed int64) { // MaxJitter will randomize over the full exponential backoff time const MaxJitter = 1.0 -// NoJitter disables the use of jitter for randomizing the exponential backoff time +// NoJitter disables the use of jitter for randomizing the +// exponential backoff time const NoJitter = 0.0 // Global random source for fetching random values. @@ -56,9 +57,11 @@ var globalRandomSource = rand.New(&lockedRandSource{ src: rand.NewSource(time.Now().UTC().UnixNano()), }) -// newRetryTimer creates a timer with exponentially increasing delays -// until the maximum retry attempts are reached. -func newRetryTimer(unit time.Duration, cap time.Duration, jitter float64, doneCh chan struct{}) <-chan int { +// newRetryTimerJitter creates a timer with exponentially increasing delays +// until the maximum retry attempts are reached. - this function is a fully +// configurable version, meant for only advanced use cases. For the most part +// one should use newRetryTimerSimple and newRetryTimer. +func newRetryTimerWithJitter(unit time.Duration, cap time.Duration, jitter float64, doneCh chan struct{}) <-chan int { attemptCh := make(chan int) // normalize jitter to the range [0, 1.0] @@ -113,5 +116,27 @@ func newRetryTimer(unit time.Duration, cap time.Duration, jitter float64, doneCh } }() + + // Start reading.. return attemptCh } + +// Default retry constants. +var ( + defaultRetryUnit = time.Second // 1 second. + defaultRetryCap = 30 * time.Second // 30 seconds. +) + +// newRetryTimer creates a timer with exponentially increasing delays +// until the maximum retry attempts are reached. - this function provides +// resulting retry values to be of maximum jitter. +func newRetryTimer(unit time.Duration, cap time.Duration, doneCh chan struct{}) <-chan int { + return newRetryTimerWithJitter(unit, cap, MaxJitter, doneCh) +} + +// newRetryTimerSimple creates a timer with exponentially increasing delays +// until the maximum retry attempts are reached. - this function is a +// simpler version with all default values. +func newRetryTimerSimple(doneCh chan struct{}) <-chan int { + return newRetryTimerWithJitter(defaultRetryUnit, defaultRetryCap, MaxJitter, doneCh) +} diff --git a/cmd/retry_test.go b/cmd/retry_test.go new file mode 100644 index 000000000..0b9614001 --- /dev/null +++ b/cmd/retry_test.go @@ -0,0 +1,82 @@ +/* + * Minio Cloud Storage, (C) 2016 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 cmd + +import ( + "testing" + "time" +) + +// Tests for retry timer. +func TestRetryTimerSimple(t *testing.T) { + doneCh := make(chan struct{}) + attemptCh := newRetryTimerSimple(doneCh) + i := <-attemptCh + if i != 0 { + close(doneCh) + t.Fatalf("Invalid attempt counter returned should be 0, found %d instead", i) + } + i = <-attemptCh + if i <= 0 { + close(doneCh) + t.Fatalf("Invalid attempt counter returned should be greater than 0, found %d instead", i) + } + close(doneCh) + _, ok := <-attemptCh + if ok { + t.Fatal("Attempt counter should be closed") + } +} + +// Test retry time with no jitter. +func TestRetryTimerWithNoJitter(t *testing.T) { + doneCh := make(chan struct{}) + // No jitter + attemptCh := newRetryTimerWithJitter(time.Millisecond, 5*time.Millisecond, NoJitter, doneCh) + i := <-attemptCh + if i != 0 { + close(doneCh) + t.Fatalf("Invalid attempt counter returned should be 0, found %d instead", i) + } + // Loop through the maximum possible attempt. + for i = range attemptCh { + if i == 30 { + close(doneCh) + } + } + _, ok := <-attemptCh + if ok { + t.Fatal("Attempt counter should be closed") + } +} + +// Test retry time with Jitter greater than MaxJitter. +func TestRetryTimerWithJitter(t *testing.T) { + doneCh := make(chan struct{}) + // Jitter will be set back to 1.0 + attemptCh := newRetryTimerWithJitter(defaultRetryUnit, defaultRetryCap, 2.0, doneCh) + i := <-attemptCh + if i != 0 { + close(doneCh) + t.Fatalf("Invalid attempt counter returned should be 0, found %d instead", i) + } + close(doneCh) + _, ok := <-attemptCh + if ok { + t.Fatal("Attempt counter should be closed") + } +} From fd72c21e0e07d9737dde6265f2c1cf44c56dab0d Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Tue, 7 Feb 2017 21:51:23 +0100 Subject: [PATCH 49/75] tests: Reduce two functions work to gain test time (#3712) TestListObjectsHeal and TestFSShutdown takes around 3 min, this PR reduces the number of created test objects --- cmd/fs-v1_test.go | 12 +++++------- cmd/xl-v1-list-objects-heal_test.go | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cmd/fs-v1_test.go b/cmd/fs-v1_test.go index 97d2d36c4..678b81b93 100644 --- a/cmd/fs-v1_test.go +++ b/cmd/fs-v1_test.go @@ -77,13 +77,11 @@ func TestFSShutdown(t *testing.T) { removeAll(disk) // Test Shutdown with faulty disk - for i := 1; i <= 5; i++ { - fs, disk := prepareTest() - fs.DeleteObject(bucketName, objectName) - removeAll(disk) - if err := fs.Shutdown(); err != nil { - t.Fatal(i, ", Got unexpected fs shutdown error: ", err) - } + fs, disk = prepareTest() + fs.DeleteObject(bucketName, objectName) + removeAll(disk) + if err := fs.Shutdown(); err != nil { + t.Fatal("Got unexpected fs shutdown error: ", err) } } diff --git a/cmd/xl-v1-list-objects-heal_test.go b/cmd/xl-v1-list-objects-heal_test.go index e21ab7765..fb515e325 100644 --- a/cmd/xl-v1-list-objects-heal_test.go +++ b/cmd/xl-v1-list-objects-heal_test.go @@ -25,6 +25,8 @@ import ( // TestListObjectsHeal - Tests ListObjectsHeal API for XL func TestListObjectsHeal(t *testing.T) { + initNSLock(false) + rootPath, err := newTestConfig(globalMinioDefaultRegion) if err != nil { t.Fatalf("Init Test config failed") @@ -49,15 +51,15 @@ func TestListObjectsHeal(t *testing.T) { t.Fatal(err) } - // Put 500 objects under sane dir - for i := 0; i < 500; i++ { + // Put 5 objects under sane dir + for i := 0; i < 5; i++ { _, err = xl.PutObject(bucketName, "sane/"+objName+strconv.Itoa(i), int64(len("abcd")), bytes.NewReader([]byte("abcd")), nil, "") if err != nil { t.Fatalf("XL Object upload failed: %s", err) } } // Put 500 objects under unsane/subdir dir - for i := 0; i < 500; i++ { + for i := 0; i < 5; i++ { _, err = xl.PutObject(bucketName, "unsane/subdir/"+objName+strconv.Itoa(i), int64(len("abcd")), bytes.NewReader([]byte("abcd")), nil, "") if err != nil { t.Fatalf("XL Object upload failed: %s", err) @@ -106,7 +108,7 @@ func TestListObjectsHeal(t *testing.T) { // Test ListObjectsHeal when all objects under unsane need healing xlObj := xl.(*xlObjects) - for i := 0; i < 500; i++ { + for i := 0; i < 5; i++ { if err = xlObj.storageDisks[0].DeleteFile(bucketName, "unsane/subdir/"+objName+strconv.Itoa(i)+"/xl.json"); err != nil { t.Fatal(err) } @@ -116,21 +118,21 @@ func TestListObjectsHeal(t *testing.T) { testCases = []testData{ // Test ListObjectsHeal when all objects under unsane/ need to be healed - {bucketName, "", "", "", 1000, nil, 500}, + {bucketName, "", "", "", 1000, nil, 5}, // List objects heal under unsane/, should return all elements - {bucketName, "unsane/", "", "", 1000, nil, 500}, + {bucketName, "unsane/", "", "", 1000, nil, 5}, // List healing objects under sane/, should return 0 {bucketName, "sane/", "", "", 1000, nil, 0}, // Max Keys == 200 - {bucketName, "unsane/", "", "", 200, nil, 200}, + {bucketName, "unsane/", "", "", 2, nil, 2}, // Max key > 1000 - {bucketName, "unsane/", "", "", 5000, nil, 500}, + {bucketName, "unsane/", "", "", 5000, nil, 5}, // Prefix == Delimiter == "/" - {bucketName, "/", "", "/", 5000, nil, 0}, + {bucketName, "/", "", "/", 1000, nil, 0}, // Max Keys == 0 {bucketName, "", "", "", 0, nil, 0}, // Testing with marker parameter - {bucketName, "", "unsane/subdir/" + objName + "0", "", 1000, nil, 499}, + {bucketName, "", "unsane/subdir/" + objName + "0", "", 1000, nil, 4}, } for i, testCase := range testCases { testFunc(testCase, i+1) From 31dff879032862f47d01778b21dffc32e8c6d549 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 7 Feb 2017 12:51:43 -0800 Subject: [PATCH 50/75] Honor envs properly for access and secret key. (#3703) Also changes the behavior of `secretKeyHash` which is not necessary to be sent over the network, each node has its own secretKeyHash to validate. Fixes #3696 Partial(fix) #3700 (More changes needed with some code cleanup) --- .travis.yml | 2 +- appveyor.yml | 4 +- cmd/admin-handlers.go | 21 +++--- cmd/admin-handlers_test.go | 1 + cmd/api-errors.go | 5 +- cmd/auth-handler_test.go | 6 +- cmd/browser-peer-rpc.go | 5 +- cmd/config-migrate_test.go | 9 +-- cmd/config-v13.go | 122 +++++++++++++++++-------------- cmd/config-v13_test.go | 2 +- cmd/credential.go | 65 +++++++++++++---- cmd/jwt.go | 24 ++++-- cmd/main.go | 47 ++++++------ cmd/server-main.go | 23 ++---- cmd/server-main_test.go | 11 ++- cmd/signature-v2_test.go | 22 ++---- cmd/test-utils_test.go | 12 ++- cmd/web-handlers.go | 24 ++++-- cmd/web-handlers_test.go | 146 +------------------------------------ 19 files changed, 237 insertions(+), 314 deletions(-) diff --git a/.travis.yml b/.travis.yml index d6976a5b9..979a61bed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ env: script: - make -- make test GOFLAGS="-timeout 15m -race -v" +- make test GOFLAGS="-timeout 20m -race -v" - make coverage after_success: diff --git a/appveyor.yml b/appveyor.yml index 7488c103a..68a87aa07 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,9 +35,9 @@ test_script: # Unit tests - ps: Add-AppveyorTest "Unit Tests" -Outcome Running - mkdir build\coverage - - go test -timeout 15m -v -race github.com/minio/minio/cmd... + - go test -timeout 20m -v -race github.com/minio/minio/cmd... - go test -v -race github.com/minio/minio/pkg... - - go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd + - go test -timeout 15m -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd - ps: Update-AppveyorTest "Unit Tests" -Outcome Passed after_test: diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index d2998c580..2773040e1 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -154,24 +154,25 @@ func (adminAPI adminAPIHandlers) ServiceCredentialsHandler(w http.ResponseWriter } // Check passed credentials - cred, err := getCredential(req.Username, req.Password) - switch err { - case errInvalidAccessKeyLength: - writeErrorResponse(w, ErrAdminInvalidAccessKey, r.URL) - return - case errInvalidSecretKeyLength: - writeErrorResponse(w, ErrAdminInvalidSecretKey, r.URL) + err = validateAuthKeys(req.Username, req.Password) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } + creds := credential{ + AccessKey: req.Username, + SecretKey: req.Password, + } + // Notify all other Minio peers to update credentials - updateErrs := updateCredsOnPeers(cred) + updateErrs := updateCredsOnPeers(creds) for peer, err := range updateErrs { errorIf(err, "Unable to update credentials on peer %s.", peer) } - // Update local credentials - serverConfig.SetCredential(cred) + // Update local credentials in memory. + serverConfig.SetCredential(creds) if err = serverConfig.Save(); err != nil { writeErrorResponse(w, ErrInternalError, r.URL) return diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index 0a8a6c96f..c6b25055b 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -43,6 +43,7 @@ type adminXLTestBed struct { func prepareAdminXLTestBed() (*adminXLTestBed, error) { // reset global variables to start afresh. resetTestGlobals() + // Initialize minio server config. rootPath, err := newTestConfig(globalMinioDefaultRegion) if err != nil { diff --git a/cmd/api-errors.go b/cmd/api-errors.go index 6ac5e7f06..656c6a39f 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -610,7 +610,10 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) { apiErr = ErrEntityTooLarge case errDataTooSmall: apiErr = ErrEntityTooSmall - + case errInvalidAccessKeyLength: + apiErr = ErrAdminInvalidAccessKey + case errInvalidSecretKeyLength: + apiErr = ErrAdminInvalidSecretKey } if apiErr != ErrNone { diff --git a/cmd/auth-handler_test.go b/cmd/auth-handler_test.go index fc48afc6c..c0e85bae2 100644 --- a/cmd/auth-handler_test.go +++ b/cmd/auth-handler_test.go @@ -315,11 +315,7 @@ func TestIsReqAuthenticated(t *testing.T) { } defer removeAll(path) - creds, err := getCredential("myuser", "mypassword") - if err != nil { - t.Fatal(err) - } - + creds := newCredentialWithKeys("myuser", "mypassword") serverConfig.SetCredential(creds) // List of test cases for validating http request authentication. diff --git a/cmd/browser-peer-rpc.go b/cmd/browser-peer-rpc.go index 335e0b770..398b907bf 100644 --- a/cmd/browser-peer-rpc.go +++ b/cmd/browser-peer-rpc.go @@ -63,13 +63,12 @@ func (br *browserPeerAPIHandlers) SetAuthPeer(args SetAuthPeerArgs, reply *AuthR return err } - creds, err := getCredential(args.Creds.AccessKey, args.Creds.SecretKey) - if err != nil { + if err := validateAuthKeys(args.Creds.AccessKey, args.Creds.SecretKey); err != nil { return err } // Update credentials in memory - serverConfig.SetCredential(creds) + serverConfig.SetCredential(args.Creds) // Save credentials to config file if err := serverConfig.Save(); err != nil { diff --git a/cmd/config-migrate_test.go b/cmd/config-migrate_test.go index c5b8a0827..b1fb6e24e 100644 --- a/cmd/config-migrate_test.go +++ b/cmd/config-migrate_test.go @@ -50,7 +50,7 @@ func TestServerConfigMigrateV1(t *testing.T) { } // Initialize server config and check again if everything is fine - if _, err := initConfig(); err != nil { + if err := loadConfig(credential{}); err != nil { t.Fatalf("Unable to initialize from updated config file %s", err) } } @@ -143,7 +143,7 @@ func TestServerConfigMigrateV2toV12(t *testing.T) { } // Initialize server config and check again if everything is fine - if _, err := initConfig(); err != nil { + if err := loadConfig(credential{}); err != nil { t.Fatalf("Unable to initialize from updated config file %s", err) } @@ -160,11 +160,6 @@ func TestServerConfigMigrateV2toV12(t *testing.T) { if serverConfig.Credential.SecretKey != secretKey { t.Fatalf("Secret key lost during migration, expected: %v, found: %v", secretKey, serverConfig.Credential.SecretKey) } - - // Initialize server config and check again if everything is fine - if _, err := initConfig(); err != nil { - t.Fatalf("Unable to initialize from updated config file %s", err) - } } // Test if all migrate code returns error with corrupted config files diff --git a/cmd/config-v13.go b/cmd/config-v13.go index 7b014fb6c..8e66c5f70 100644 --- a/cmd/config-v13.go +++ b/cmd/config-v13.go @@ -42,77 +42,88 @@ type serverConfigV13 struct { Notify notifier `json:"notify"` } -// initConfig - initialize server config and indicate if we are -// creating a new file or we are just loading -func initConfig() (bool, error) { - if !isConfigFileExists() { - // Initialize server config. - srvCfg := &serverConfigV13{} - srvCfg.Version = globalMinioConfigVersion - srvCfg.Region = globalMinioDefaultRegion - srvCfg.Credential = newCredential() +// newConfig - initialize a new server config, saves creds from env +// if globalIsEnvCreds is set otherwise generates a new set of keys +// and those are saved. +func newConfig(envCreds credential) error { + // Initialize server config. + srvCfg := &serverConfigV13{} + srvCfg.Version = globalMinioConfigVersion + srvCfg.Region = globalMinioDefaultRegion - // Enable console logger by default on a fresh run. - srvCfg.Logger.Console = consoleLogger{ - Enable: true, - Level: "error", - } - - // Make sure to initialize notification configs. - srvCfg.Notify.AMQP = make(map[string]amqpNotify) - srvCfg.Notify.AMQP["1"] = amqpNotify{} - srvCfg.Notify.ElasticSearch = make(map[string]elasticSearchNotify) - srvCfg.Notify.ElasticSearch["1"] = elasticSearchNotify{} - srvCfg.Notify.Redis = make(map[string]redisNotify) - srvCfg.Notify.Redis["1"] = redisNotify{} - srvCfg.Notify.NATS = make(map[string]natsNotify) - srvCfg.Notify.NATS["1"] = natsNotify{} - srvCfg.Notify.PostgreSQL = make(map[string]postgreSQLNotify) - srvCfg.Notify.PostgreSQL["1"] = postgreSQLNotify{} - srvCfg.Notify.Kafka = make(map[string]kafkaNotify) - srvCfg.Notify.Kafka["1"] = kafkaNotify{} - srvCfg.Notify.Webhook = make(map[string]webhookNotify) - srvCfg.Notify.Webhook["1"] = webhookNotify{} - - // Create config path. - err := createConfigPath() - if err != nil { - return false, err - } - - // hold the mutex lock before a new config is assigned. - // Save the new config globally. - // unlock the mutex. - serverConfigMu.Lock() - serverConfig = srvCfg - serverConfigMu.Unlock() - - // Save config into file. - return true, serverConfig.Save() + // If env is set for a fresh start, save them to config file. + if globalIsEnvCreds { + srvCfg.SetCredential(envCreds) + } else { + srvCfg.SetCredential(newCredential()) } + // Enable console logger by default on a fresh run. + srvCfg.Logger.Console = consoleLogger{ + Enable: true, + Level: "error", + } + + // Make sure to initialize notification configs. + srvCfg.Notify.AMQP = make(map[string]amqpNotify) + srvCfg.Notify.AMQP["1"] = amqpNotify{} + srvCfg.Notify.ElasticSearch = make(map[string]elasticSearchNotify) + srvCfg.Notify.ElasticSearch["1"] = elasticSearchNotify{} + srvCfg.Notify.Redis = make(map[string]redisNotify) + srvCfg.Notify.Redis["1"] = redisNotify{} + srvCfg.Notify.NATS = make(map[string]natsNotify) + srvCfg.Notify.NATS["1"] = natsNotify{} + srvCfg.Notify.PostgreSQL = make(map[string]postgreSQLNotify) + srvCfg.Notify.PostgreSQL["1"] = postgreSQLNotify{} + srvCfg.Notify.Kafka = make(map[string]kafkaNotify) + srvCfg.Notify.Kafka["1"] = kafkaNotify{} + srvCfg.Notify.Webhook = make(map[string]webhookNotify) + srvCfg.Notify.Webhook["1"] = webhookNotify{} + + // Create config path. + if err := createConfigPath(); err != nil { + return err + } + + // hold the mutex lock before a new config is assigned. + // Save the new config globally. + // unlock the mutex. + serverConfigMu.Lock() + serverConfig = srvCfg + serverConfigMu.Unlock() + + // Save config into file. + return serverConfig.Save() +} + +// loadConfig - loads a new config from disk, overrides creds from env +// if globalIsEnvCreds is set otherwise serves the creds from loaded +// from the disk. +func loadConfig(envCreds credential) error { configFile, err := getConfigFile() if err != nil { - return false, err + return err } if _, err = os.Stat(configFile); err != nil { - return false, err + return err } srvCfg := &serverConfigV13{} srvCfg.Version = globalMinioConfigVersion qc, err := quick.New(srvCfg) if err != nil { - return false, err + return err } if err = qc.Load(configFile); err != nil { - return false, err + return err } - srvCfg.Credential, err = getCredential(srvCfg.Credential.AccessKey, srvCfg.Credential.SecretKey) - if err != nil { - return false, err + // If env is set override the credentials from config file. + if globalIsEnvCreds { + srvCfg.SetCredential(envCreds) + } else { + srvCfg.SetCredential(srvCfg.Credential) } // hold the mutex lock before a new config is assigned. @@ -123,8 +134,7 @@ func initConfig() (bool, error) { // Set the version properly after the unmarshalled json is loaded. serverConfig.Version = globalMinioConfigVersion - - return false, nil + return nil } // serverConfig server config. @@ -347,7 +357,7 @@ func (s *serverConfigV13) SetCredential(creds credential) { defer serverConfigMu.Unlock() // Set updated credential. - s.Credential = creds + s.Credential = newCredentialWithKeys(creds.AccessKey, creds.SecretKey) } // GetCredentials get current credentials. diff --git a/cmd/config-v13_test.go b/cmd/config-v13_test.go index 54312714e..b620b00ff 100644 --- a/cmd/config-v13_test.go +++ b/cmd/config-v13_test.go @@ -106,7 +106,7 @@ func TestServerConfig(t *testing.T) { setGlobalConfigPath(rootPath) // Initialize server config. - if _, err := initConfig(); err != nil { + if err := loadConfig(credential{}); err != nil { t.Fatalf("Unable to initialize from updated config file %s", err) } } diff --git a/cmd/credential.go b/cmd/credential.go index aad1749b1..c75049050 100644 --- a/cmd/credential.go +++ b/cmd/credential.go @@ -19,6 +19,9 @@ package cmd import ( "crypto/rand" "encoding/base64" + "os" + + "github.com/minio/mc/pkg/console" "golang.org/x/crypto/bcrypt" ) @@ -36,7 +39,7 @@ const ( func mustGetAccessKey() string { keyBytes := make([]byte, accessKeyMaxLen) if _, err := rand.Read(keyBytes); err != nil { - panic(err) + console.Fatalf("Unable to generate access key. Err: %s.\n", err) } for i := 0; i < accessKeyMaxLen; i++ { @@ -49,7 +52,7 @@ func mustGetAccessKey() string { func mustGetSecretKey() string { keyBytes := make([]byte, secretKeyMaxLen) if _, err := rand.Read(keyBytes); err != nil { - panic(err) + console.Fatalf("Unable to generate secret key. Err: %s.\n", err) } return string([]byte(base64.StdEncoding.EncodeToString(keyBytes))[:secretKeyMaxLen]) @@ -69,38 +72,68 @@ func isSecretKeyValid(secretKey string) bool { type credential struct { AccessKey string `json:"accessKey,omitempty"` SecretKey string `json:"secretKey,omitempty"` - SecretKeyHash []byte `json:"secretKeyHash,omitempty"` + secretKeyHash []byte } // Generate a bcrypt hashed key for input secret key. func mustGetHashedSecretKey(secretKey string) []byte { hashedSecretKey, err := bcrypt.GenerateFromPassword([]byte(secretKey), bcrypt.DefaultCost) if err != nil { - panic(err) + console.Fatalf("Unable to generate secret hash for secret key. Err: %s.\n", err) } return hashedSecretKey } -// Initialize a new credential object. +// Initialize a new credential object func newCredential() credential { - secretKey := mustGetSecretKey() - accessKey := mustGetAccessKey() + return newCredentialWithKeys(mustGetAccessKey(), mustGetSecretKey()) +} +func newCredentialWithKeys(accessKey, secretKey string) credential { secretHash := mustGetHashedSecretKey(secretKey) return credential{accessKey, secretKey, secretHash} } +// Validate incoming auth keys. +func validateAuthKeys(accessKey, secretKey string) error { + // Validate the env values before proceeding. + if !isAccessKeyValid(accessKey) { + return errInvalidAccessKeyLength + } + if !isSecretKeyValid(secretKey) { + return errInvalidSecretKeyLength + } + return nil +} + +// Variant of getCredentialFromEnv but upon error fails right here. +func mustGetCredentialFromEnv() credential { + creds, err := getCredentialFromEnv() + if err != nil { + console.Fatalf("Unable to load credentials from environment. Err: %s.\n", err) + } + return creds +} + // Converts accessKey and secretKeys into credential object which // contains bcrypt secret key hash for future validation. -func getCredential(accessKey, secretKey string) (credential, error) { - if !isAccessKeyValid(accessKey) { - return credential{}, errInvalidAccessKeyLength +func getCredentialFromEnv() (credential, error) { + // Fetch access keys from environment variables and update the config. + accessKey := os.Getenv("MINIO_ACCESS_KEY") + secretKey := os.Getenv("MINIO_SECRET_KEY") + + // Envs are set globally. + globalIsEnvCreds = accessKey != "" && secretKey != "" + + if globalIsEnvCreds { + // Validate the env values before proceeding. + if err := validateAuthKeys(accessKey, secretKey); err != nil { + return credential{}, err + } + + // Return credential object. + return newCredentialWithKeys(accessKey, secretKey), nil } - if !isSecretKeyValid(secretKey) { - return credential{}, errInvalidSecretKeyLength - } - - secretHash := mustGetHashedSecretKey(secretKey) - return credential{accessKey, secretKey, secretHash}, nil + return credential{}, nil } diff --git a/cmd/jwt.go b/cmd/jwt.go index f1f0b2373..54f4668f7 100644 --- a/cmd/jwt.go +++ b/cmd/jwt.go @@ -38,12 +38,15 @@ const ( defaultInterNodeJWTExpiry = 100 * 365 * 24 * time.Hour ) -var errInvalidAccessKeyLength = errors.New("Invalid access key, access key should be 5 to 20 characters in length") -var errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 40 characters in length") +var ( + errInvalidAccessKeyLength = errors.New("Invalid access key, access key should be 5 to 20 characters in length") + errInvalidSecretKeyLength = errors.New("Invalid secret key, secret key should be 8 to 40 characters in length") -var errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records") -var errAuthentication = errors.New("Authentication failed, check your access credentials") -var errNoAuthToken = errors.New("JWT token missing") + errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records") + errChangeCredNotAllowed = errors.New("Changing access key and secret key not allowed") + errAuthentication = errors.New("Authentication failed, check your access credentials") + errNoAuthToken = errors.New("JWT token missing") +) func authenticateJWT(accessKey, secretKey string, expiry time.Duration) (string, error) { // Trim spaces. @@ -65,8 +68,15 @@ func authenticateJWT(accessKey, secretKey string, expiry time.Duration) (string, // Validate secret key. // Using bcrypt to avoid timing attacks. - if bcrypt.CompareHashAndPassword(serverCred.SecretKeyHash, []byte(secretKey)) != nil { - return "", errAuthentication + if serverCred.secretKeyHash != nil { + if bcrypt.CompareHashAndPassword(serverCred.secretKeyHash, []byte(secretKey)) != nil { + return "", errAuthentication + } + } else { + // Secret key hash not set then generate and validate. + if bcrypt.CompareHashAndPassword(mustGetHashedSecretKey(serverCred.SecretKey), []byte(secretKey)) != nil { + return "", errAuthentication + } } utcNow := time.Now().UTC() diff --git a/cmd/main.go b/cmd/main.go index 57c42772a..e6db20ad6 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -163,6 +163,29 @@ func checkUpdate() { } } +// Initializes a new config if it doesn't exist, else migrates any old config +// to newer config and finally loads the config to memory. +func initConfig() { + envCreds := mustGetCredentialFromEnv() + + // Config file does not exist, we create it fresh and return upon success. + if !isConfigFileExists() { + if err := newConfig(envCreds); err != nil { + console.Fatalf("Unable to initialize minio config for the first time. Err: %s.\n", err) + } + console.Println("Created minio configuration file successfully at " + mustGetConfigPath()) + return + } + + // Migrate any old version of config / state files to newer format. + migrate() + + // Once we have migrated all the old config, now load them. + if err := loadConfig(envCreds); err != nil { + console.Fatalf("Unable to initialize minio config. Err: %s.\n", err) + } +} + // Generic Minio initialization to create/load config, prepare loggers, etc.. func minioInit(ctx *cli.Context) { // Set global variables after parsing passed arguments @@ -174,32 +197,12 @@ func minioInit(ctx *cli.Context) { // Is TLS configured?. globalIsSSL = isSSL() - // Migrate any old version of config / state files to newer format. - migrate() - - // Initialize config. - configCreated, err := initConfig() - if err != nil { - console.Fatalf("Unable to initialize minio config. Err: %s.\n", err) - } - if configCreated { - console.Println("Created minio configuration file at " + mustGetConfigPath()) - } + // Initialize minio server config. + initConfig() // Enable all loggers by now so we can use errorIf() and fatalIf() enableLoggers() - // Fetch access keys from environment variables and update the config. - accessKey := os.Getenv("MINIO_ACCESS_KEY") - secretKey := os.Getenv("MINIO_SECRET_KEY") - if accessKey != "" && secretKey != "" { - creds, err := getCredential(accessKey, secretKey) - fatalIf(err, "Credentials are invalid, please set proper credentials `minio server --help`") - - // Set new credentials. - serverConfig.SetCredential(creds) - } - // Init the error tracing module. initError() diff --git a/cmd/server-main.go b/cmd/server-main.go index e54143d73..3164c5783 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -21,7 +21,6 @@ import ( "fmt" "net" "net/url" - "os" "path" "sort" "strconv" @@ -128,22 +127,17 @@ func parseStorageEndpoints(eps []string) (endpoints []*url.URL, err error) { return endpoints, nil } -// initServerConfig initialize server config. +// initServer initialize server config. func initServerConfig(c *cli.Context) { + // Initialization such as config generating/loading config, enable logging, .. + minioInit(c) + // Create certs path. - err := createCertsPath() - fatalIf(err, "Unable to create \"certs\" directory.") + fatalIf(createCertsPath(), "Unable to create \"certs\" directory.") // Load user supplied root CAs loadRootCAs() - // When credentials inherited from the env, server cmd has to save them in the disk - if os.Getenv("MINIO_ACCESS_KEY") != "" && os.Getenv("MINIO_SECRET_KEY") != "" { - // Env credentials are already loaded in serverConfig, just save in the disk - err = serverConfig.Save() - fatalIf(err, "Unable to save credentials in the disk.") - } - // Set maxOpenFiles, This is necessary since default operating // system limits of 1024, 2048 are not enough for Minio server. setMaxOpenFiles() @@ -372,8 +366,8 @@ func serverMain(c *cli.Context) { cli.ShowCommandHelpAndExit(c, "server", 1) } - // Initialization routine, such as config loading, enable logging, .. - minioInit(c) + // Initializes server config, certs, logging and system settings. + initServerConfig(c) // Check for new updates from dl.minio.io. checkUpdate() @@ -390,9 +384,6 @@ func serverMain(c *cli.Context) { // as parseStorageEndpoints() depends on it. checkServerSyntax(c) - // Initialize server config. - initServerConfig(c) - // Disks to be used in server init. endpoints, err := parseStorageEndpoints(c.Args()) fatalIf(err, "Unable to parse storage endpoints %s", c.Args()) diff --git a/cmd/server-main_test.go b/cmd/server-main_test.go index 5fbc17029..cf49c9086 100644 --- a/cmd/server-main_test.go +++ b/cmd/server-main_test.go @@ -452,8 +452,14 @@ func TestIsDistributedSetup(t *testing.T) { globalMinioHost = "" } -func TestInitServerConfig(t *testing.T) { - ctx := &cli.Context{} +// Tests init server. +func TestInitServer(t *testing.T) { + app := cli.NewApp() + app.Commands = []cli.Command{serverCmd} + serverFlagSet := flag.NewFlagSet("server", 0) + serverFlagSet.String("address", ":9000", "") + ctx := cli.NewContext(app, serverFlagSet, serverFlagSet) + root, err := newTestConfig(globalMinioDefaultRegion) if err != nil { t.Fatal("Failed to set up test config") @@ -473,6 +479,7 @@ func TestInitServerConfig(t *testing.T) { t.Fatalf("Test %d failed with %v", i+1, tErr) } initServerConfig(ctx) + os.Unsetenv(test.envVar) } } diff --git a/cmd/signature-v2_test.go b/cmd/signature-v2_test.go index 56cc38957..fc5b2dee9 100644 --- a/cmd/signature-v2_test.go +++ b/cmd/signature-v2_test.go @@ -119,17 +119,13 @@ func TestDoesPresignedV2SignatureMatch(t *testing.T) { // TestValidateV2AuthHeader - Tests validate the logic of V2 Authorization header validator. func TestValidateV2AuthHeader(t *testing.T) { - // Initialize server config. - if _, err := initConfig(); err != nil { - t.Fatal(err) + root, err := newTestConfig(globalMinioDefaultRegion) + if err != nil { + t.Fatal("Unable to initialize test config.") } + defer removeAll(root) - // Save config. - if err := serverConfig.Save(); err != nil { - t.Fatal(err) - } accessID := serverConfig.GetCredential().AccessKey - testCases := []struct { authString string expectedError APIErrorCode @@ -194,13 +190,11 @@ func TestValidateV2AuthHeader(t *testing.T) { } func TestDoesPolicySignatureV2Match(t *testing.T) { - if _, err := initConfig(); err != nil { - t.Fatal(err) - } - - if err := serverConfig.Save(); err != nil { - t.Fatal(err) + root, err := newTestConfig(globalMinioDefaultRegion) + if err != nil { + t.Fatal("Unable to initialize test config.") } + defer removeAll(root) creds := serverConfig.GetCredential() policy := "policy" testCases := []struct { diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 67219df0c..7ef2f25b2 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -496,6 +496,10 @@ func resetGlobalIsXL() { globalIsXL = false } +func resetGlobalIsEnvs() { + globalIsEnvCreds = false +} + // Resets all the globals used modified in tests. // Resetting ensures that the changes made to globals by one test doesn't affect others. func resetTestGlobals() { @@ -513,6 +517,8 @@ func resetTestGlobals() { resetGlobalEndpoints() // Reset global isXL flag. resetGlobalIsXL() + // Reset global isEnvCreds flag. + resetGlobalIsEnvs() } // Configure the server for the test run. @@ -527,7 +533,7 @@ func newTestConfig(bucketLocation string) (rootPath string, err error) { setGlobalConfigPath(rootPath) // Initialize server config. - if _, err = initConfig(); err != nil { + if err = newConfig(credential{}); err != nil { return "", err } @@ -1790,6 +1796,7 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, failTestStr := func(testType, failMsg string) string { return fmt.Sprintf("Minio %s: %s fail for \"%s\": \n %s", instanceType, testType, testName, failMsg) } + // httptest Recorder to capture all the response by the http handler. rec := httptest.NewRecorder() // reading the body to preserve it so that it can be used again for second attempt of sending unsigned HTTP request. @@ -1941,8 +1948,10 @@ func ExecObjectLayerAPITest(t *testing.T, objAPITest objAPITestType, endpoints [ // reset globals. // this is to make sure that the tests are not affected by modified value. resetTestGlobals() + // initialize NSLock. initNSLock(false) + // initialize the server and obtain the credentials and root. // credentials are necessary to sign the HTTP request. rootPath, err := newTestConfig(globalMinioDefaultRegion) @@ -2025,6 +2034,7 @@ func ExecObjectLayerDiskAlteredTest(t *testing.T, objTest objTestDiskNotFoundTyp if err != nil { t.Fatalf("Initialization of object layer failed for XL setup: %s", err) } + // Executing the object layer tests for XL. objTest(objLayer, XLTestStr, fsDirs, t) defer removeRoots(fsDirs) diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index d3f65a0e8..53daca3cc 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -362,12 +362,21 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se return toJSONError(errAuthentication) } + // If creds are set through ENV disallow changing credentials. + if globalIsEnvCreds { + return toJSONError(errChangeCredNotAllowed) + } + // As we already validated the authentication, we save given access/secret keys. - creds, err := getCredential(args.AccessKey, args.SecretKey) - if err != nil { + if err := validateAuthKeys(args.AccessKey, args.SecretKey); err != nil { return toJSONError(err) } + creds := credential{ + AccessKey: args.AccessKey, + SecretKey: args.SecretKey, + } + // Notify all other Minio peers to update credentials errsMap := updateCredsOnPeers(creds) @@ -375,7 +384,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se serverConfig.SetCredential(creds) // Persist updated credentials. - if err = serverConfig.Save(); err != nil { + if err := serverConfig.Save(); err != nil { errsMap[globalMinioAddr] = err } @@ -397,7 +406,7 @@ func (web *webAPIHandlers) SetAuth(r *http.Request, args *SetAuthArgs, reply *Se } // As we have updated access/secret key, generate new auth token. - token, err := authenticateWeb(args.AccessKey, args.SecretKey) + token, err := authenticateWeb(creds.AccessKey, creds.SecretKey) if err != nil { // Did we have peer errors? if len(errsMap) > 0 { @@ -829,8 +838,13 @@ func toWebAPIError(err error) APIError { HTTPStatusCode: http.StatusBadRequest, Description: err.Error(), } + } else if err == errChangeCredNotAllowed { + return APIError{ + Code: "MethodNotAllowed", + HTTPStatusCode: http.StatusMethodNotAllowed, + Description: err.Error(), + } } - // Convert error type to api error code. var apiErrCode APIErrorCode switch err.(type) { diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index 1f8c9e627..ae0c2576a 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -128,15 +128,6 @@ func TestWebHandlerLogin(t *testing.T) { func testLoginWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() // test cases with sample input and expected output. @@ -177,15 +168,6 @@ func testStorageInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHa // get random bucket name. // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -223,15 +205,6 @@ func TestWebHandlerServerInfo(t *testing.T) { func testServerInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -269,15 +242,6 @@ func TestWebHandlerMakeBucket(t *testing.T) { func testMakeBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -329,15 +293,6 @@ func TestWebHandlerListBuckets(t *testing.T) { func testListBucketsWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -386,15 +341,6 @@ func TestWebHandlerListObjects(t *testing.T) { func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() rec := httptest.NewRecorder() @@ -490,15 +436,6 @@ func TestWebHandlerRemoveObject(t *testing.T) { func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() rec := httptest.NewRecorder() @@ -566,15 +503,6 @@ func TestWebHandlerGenerateAuth(t *testing.T) { func testGenerateAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() rec := httptest.NewRecorder() @@ -612,15 +540,6 @@ func TestWebHandlerSetAuth(t *testing.T) { func testSetAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() rec := httptest.NewRecorder() @@ -673,15 +592,6 @@ func TestWebHandlerGetAuth(t *testing.T) { func testGetAuthWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() rec := httptest.NewRecorder() @@ -718,18 +628,9 @@ func TestWebHandlerUpload(t *testing.T) { func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() - content := []byte("temporary file's content") + content := []byte("temporary file's content") authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) if err != nil { t.Fatal("Cannot authenticate") @@ -820,15 +721,6 @@ func TestWebHandlerDownload(t *testing.T) { func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -912,15 +804,6 @@ func TestWebHandlerPresignedGetHandler(t *testing.T) { func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -1025,15 +908,6 @@ func TestWebHandlerGetBucketPolicyHandler(t *testing.T) { func testWebGetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -1108,15 +982,6 @@ func TestWebHandlerListAllBucketPoliciesHandler(t *testing.T) { func testWebListAllBucketPoliciesHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) @@ -1214,15 +1079,6 @@ func TestWebHandlerSetBucketPolicyHandler(t *testing.T) { func testWebSetBucketPolicyHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { // Register the API end points with XL/FS object layer. apiRouter := initTestWebRPCEndPoint(obj) - // initialize the server and obtain the credentials and root. - // credentials are necessary to sign the HTTP request. - rootPath, err := newTestConfig(globalMinioDefaultRegion) - if err != nil { - t.Fatalf("Init Test config failed") - } - // remove the root directory after the test ends. - defer removeAll(rootPath) - credentials := serverConfig.GetCredential() authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) From 7547f3c8a3128e0c51e443d251cb1caf6f171c1e Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Wed, 8 Feb 2017 12:49:32 +0530 Subject: [PATCH 51/75] Added Webhook notification details (#3706) --- docs/bucket/notifications/README.md | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/bucket/notifications/README.md b/docs/bucket/notifications/README.md index 76a74dee2..7e49aef75 100644 --- a/docs/bucket/notifications/README.md +++ b/docs/bucket/notifications/README.md @@ -10,6 +10,7 @@ Minio server supports Amazon S3 compatible bucket event notification for the fol | [`NATS`](#NATS) | | [`PostgreSQL`](#PostgreSQL) | | [`Apache Kafka`](#apache-kafka) | +| [`Webhooks`](#webhooks) | ## Prerequisites @@ -474,4 +475,70 @@ mc cp myphoto.jpg myminio/images kafkacat -b localhost:9092 -t bucketevents {"EventType":"s3:ObjectCreated:Put","Key":"images/myphoto.jpg","Records":[{"eventVersion":"2.0","eventSource":"aws:s3","awsRegion":"us-east-1","eventTime":"2017-01-31T10:01:51Z","eventName":"s3:ObjectCreated:Put","userIdentity":{"principalId":"88QR09S7IOT4X1IBAQ9B"},"requestParameters":{"sourceIPAddress":"192.173.5.2:57904"},"responseElements":{"x-amz-request-id":"149ED2FD25589220","x-minio-origin-endpoint":"http://192.173.5.2:9000"},"s3":{"s3SchemaVersion":"1.0","configurationId":"Config","bucket":{"name":"images","ownerIdentity":{"principalId":"88QR09S7IOT4X1IBAQ9B"},"arn":"arn:aws:s3:::images"},"object":{"key":"myphoto.jpg","size":541596,"eTag":"04451d05b4faf4d62f3d538156115e2a","sequencer":"149ED2FD25589220"}}}],"level":"info","msg":"","time":"2017-01-31T15:31:51+05:30"} ``` + + +## Publish Minio events via Webhooks + +[Webhooks](https://en.wikipedia.org/wiki/Webhook) are a way to receive information when it happens, rather than continually polling for that data. + +### Step 1: Add Webhook endpoint to Minio + +The default location of Minio server configuration file is ``~/.minio/config.json``. Update the Webhook configuration block in ``config.json`` as follows + +``` +"webhook": { + "1": { + "enable": true, + "endpoint": "http://localhost:3000/" +} +``` +Here the endpoint is the server listening for webhook notifications. Save the file and restart the Minio server for changes to take effect. Note that the endpoint needs to be live and reachable when you restart your Minio server. + +### Step 2: Enable bucket notification using Minio client + +We will enable bucket event notification to trigger whenever a JPEG image is uploaded to ``images`` bucket on ``myminio`` server. Here ARN value is ``arn:minio:sqs:us-east-1:1:webhook``. To learn more about ARN please follow [AWS ARN](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) documentation. + +``` +mc mb myminio/images +mc mb myminio/images-thumbnail +mc events add myminio/images arn:minio:sqs:us-east-1:1:webhook — events put — suffix .jpg +``` +Check if event notification is successfully configured by +``` +mc events list myminio/images +``` +You should get a response like this +``` +arn:minio:sqs:us-east-1:1:webhook s3:ObjectCreated:* Filter: suffix=".jpg" +``` + +### Step 3: Test with Thumbnailer + +We used [Thumbnailer](https://github.com/minio/thumbnailer) to listen for Minio notifications when a new JPEG file is uploaded (HTTP PUT). Triggered by a notification, Thumbnailer uploads a thumbnail of new image to Minio server. To start with, download and install Thumbnailer. + +``` +git clone https://github.com/minio/thumbnailer/ +npm install +``` + +Then open the Thumbnailer config file at ``config/webhook.json`` and add the configuration for your Minio server and then start Thumbnailer by + +``` +NODE_ENV=webhook node thumbnail-webhook.js +``` + +Thumbnailer starts running at ``http://localhost:3000/``. Next, configure the Minio server to send notifications to this URL (as mentioned in step 1) and use ``mc`` to set up bucket notifications (as mentioned in step 2). Then upload a JPEG image to Minio server by + +``` +mc cp ~/images.jpg myminio/images +.../images.jpg: 8.31 KB / 8.31 KB ┃▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓┃ 100.00% 59.42 KB/s 0s +``` +Wait a few moments, then check the bucket’s contents with mc ls — you will see a thumbnail appear. + +``` +mc ls myminio/images-thumbnail +[2017-02-08 11:39:40 IST] 992B images-thumbnail.jpg +``` + + *NOTE* If you are running [distributed Minio](https://docs.minio.io/docs/distributed-minio-quickstart-guide), modify ``~/.minio/config.json`` on all the nodes with your bucket event notification backend configuration. From ce9aa2f2b2fbf93592a7ee4ff79b6acda6b42dbf Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Wed, 8 Feb 2017 13:43:02 +0530 Subject: [PATCH 52/75] Add uptime to ServiceStatus (#3690) --- cmd/admin-handlers.go | 19 ++++---- cmd/admin-handlers_test.go | 7 ++- cmd/admin-rpc-client.go | 86 ++++++++++++++++++++++++++++++++++ cmd/admin-rpc-server.go | 27 +++++++++++ cmd/globals.go | 4 ++ cmd/server-main.go | 4 ++ pkg/madmin/service-commands.go | 2 + 7 files changed, 139 insertions(+), 10 deletions(-) diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 2773040e1..4a7bb547b 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -19,7 +19,6 @@ package cmd import ( "encoding/json" "encoding/xml" - "fmt" "io/ioutil" "net/http" "net/url" @@ -54,8 +53,8 @@ type ServerVersion struct { // ServerStatus - contains the response of service status API type ServerStatus struct { - StorageInfo StorageInfo `json:"storageInfo"` ServerVersion ServerVersion `json:"serverVersion"` + Uptime time.Duration `json:"uptime"` } // ServiceStatusHandler - GET /?service @@ -70,15 +69,22 @@ func (adminAPI adminAPIHandlers) ServiceStatusHandler(w http.ResponseWriter, r * return } - // Fetch storage backend information - storageInfo := newObjectLayerFn().StorageInfo() // Fetch server version serverVersion := ServerVersion{Version: Version, CommitID: CommitID} + // Fetch uptimes from all peers. This may fail to due to lack + // of read-quorum availability. + uptime, err := getPeerUptimes(globalAdminPeers) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + errorIf(err, "Possibly failed to get uptime from majority of servers.") + return + } + // Create API response serverStatus := ServerStatus{ - StorageInfo: storageInfo, ServerVersion: serverVersion, + Uptime: uptime, } // Marshal API response @@ -542,7 +548,6 @@ func (adminAPI adminAPIHandlers) HealFormatHandler(w http.ResponseWriter, r *htt // Create a new set of storage instances to heal format.json. bootstrapDisks, err := initStorageDisks(globalEndpoints) if err != nil { - fmt.Println(traceError(err)) writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } @@ -550,7 +555,6 @@ func (adminAPI adminAPIHandlers) HealFormatHandler(w http.ResponseWriter, r *htt // Heal format.json on available storage. err = healFormatXL(bootstrapDisks) if err != nil { - fmt.Println(traceError(err)) writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } @@ -558,7 +562,6 @@ func (adminAPI adminAPIHandlers) HealFormatHandler(w http.ResponseWriter, r *htt // Instantiate new object layer with newly formatted storage. newObjectAPI, err := newXLObjects(bootstrapDisks) if err != nil { - fmt.Println(traceError(err)) writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index c6b25055b..e576a5304 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -25,6 +25,7 @@ import ( "net/http/httptest" "net/url" "testing" + "time" router "github.com/gorilla/mux" ) @@ -55,6 +56,9 @@ func prepareAdminXLTestBed() (*adminXLTestBed, error) { return nil, xlErr } + // Initialize boot time + globalBootTime = time.Now().UTC() + // Set globalEndpoints for a single node XL setup. for _, xlDir := range xlDirs { globalEndpoints = append(globalEndpoints, &url.URL{ @@ -225,14 +229,13 @@ func testServicesCmdHandler(cmd cmdType, t *testing.T) { if cmd == statusCmd { expectedInfo := ServerStatus{ - StorageInfo: newObjectLayerFn().StorageInfo(), ServerVersion: ServerVersion{Version: Version, CommitID: CommitID}, } receivedInfo := ServerStatus{} if jsonErr := json.Unmarshal(rec.Body.Bytes(), &receivedInfo); jsonErr != nil { t.Errorf("Failed to unmarshal StorageInfo - %v", jsonErr) } - if expectedInfo != receivedInfo { + if expectedInfo.ServerVersion != receivedInfo.ServerVersion { t.Errorf("Expected storage info and received storage info differ, %v %v", expectedInfo, receivedInfo) } } diff --git a/cmd/admin-rpc-client.go b/cmd/admin-rpc-client.go index b963cbd6a..58a83cd0c 100644 --- a/cmd/admin-rpc-client.go +++ b/cmd/admin-rpc-client.go @@ -19,6 +19,7 @@ package cmd import ( "net/url" "path" + "sort" "sync" "time" ) @@ -39,6 +40,7 @@ type adminCmdRunner interface { Restart() error ListLocks(bucket, prefix string, duration time.Duration) ([]VolumeLockInfo, error) ReInitDisks() error + Uptime() (time.Duration, error) } // Restart - Sends a message over channel to the go-routine @@ -88,6 +90,28 @@ func (rc remoteAdminClient) ReInitDisks() error { return rc.Call("Admin.ReInitDisks", &args, &reply) } +// Uptime - Returns the uptime of this server. Timestamp is taken +// after object layer is initialized. +func (lc localAdminClient) Uptime() (time.Duration, error) { + if globalBootTime.IsZero() { + return time.Duration(0), errServerNotInitialized + } + + return time.Now().UTC().Sub(globalBootTime), nil +} + +// Uptime - returns the uptime of the server to which the RPC call is made. +func (rc remoteAdminClient) Uptime() (time.Duration, error) { + args := AuthRPCArgs{} + reply := UptimeReply{} + err := rc.Call("Admin.Uptime", &args, &reply) + if err != nil { + return time.Duration(0), err + } + + return reply.Uptime, nil +} + // adminPeer - represents an entity that implements Restart methods. type adminPeer struct { addr string @@ -241,3 +265,65 @@ func reInitPeerDisks(peers adminPeers) error { wg.Wait() return nil } + +// uptimeSlice - used to sort uptimes in chronological order. +type uptimeSlice []struct { + err error + uptime time.Duration +} + +func (ts uptimeSlice) Len() int { + return len(ts) +} + +func (ts uptimeSlice) Less(i, j int) bool { + return ts[i].uptime < ts[j].uptime +} + +func (ts uptimeSlice) Swap(i, j int) { + ts[i], ts[j] = ts[j], ts[i] +} + +// getPeerUptimes - returns the uptime since the last time read quorum +// was established on success. Otherwise returns errXLReadQuorum. +func getPeerUptimes(peers adminPeers) (time.Duration, error) { + uptimes := make(uptimeSlice, len(peers)) + + // Get up time of all servers. + wg := sync.WaitGroup{} + for i, peer := range peers { + wg.Add(1) + go func(idx int, peer adminPeer) { + defer wg.Done() + uptimes[idx].uptime, uptimes[idx].err = peer.cmdRunner.Uptime() + }(i, peer) + } + wg.Wait() + + // Sort uptimes in chronological order. + sort.Sort(uptimes) + + // Pick the readQuorum'th uptime in chronological order. i.e, + // the time at which read quorum was (re-)established. + readQuorum := len(uptimes) / 2 + validCount := 0 + latestUptime := time.Duration(0) + for _, uptime := range uptimes { + if uptime.err != nil { + continue + } + + validCount++ + if validCount >= readQuorum { + latestUptime = uptime.uptime + break + } + } + + // This implies there weren't read quorum number of servers up. + if latestUptime == time.Duration(0) { + return time.Duration(0), InsufficientReadQuorum{} + } + + return latestUptime, nil +} diff --git a/cmd/admin-rpc-server.go b/cmd/admin-rpc-server.go index fa5d5e781..d5f8178bd 100644 --- a/cmd/admin-rpc-server.go +++ b/cmd/admin-rpc-server.go @@ -48,6 +48,12 @@ type ListLocksReply struct { volLocks []VolumeLockInfo } +// UptimeReply - wraps the uptime response over RPC. +type UptimeReply struct { + AuthRPCReply + Uptime time.Duration +} + // Restart - Restart this instance of minio server. func (s *adminCmd) Restart(args *AuthRPCArgs, reply *AuthRPCReply) error { if err := args.IsAuthenticated(); err != nil { @@ -105,6 +111,27 @@ func (s *adminCmd) ReInitDisks(args *AuthRPCArgs, reply *AuthRPCReply) error { return nil } +// Uptime - returns the time when object layer was initialized on this server. +func (s *adminCmd) Uptime(args *AuthRPCArgs, reply *UptimeReply) error { + if err := args.IsAuthenticated(); err != nil { + return err + } + + if globalBootTime.IsZero() { + return errServerNotInitialized + } + + // N B The uptime is computed assuming that the system time is + // monotonic. This is not the case in time pkg in Go, see + // https://github.com/golang/go/issues/12914. This is expected + // to be fixed by go1.9. + *reply = UptimeReply{ + Uptime: time.Now().UTC().Sub(globalBootTime), + } + + return nil +} + // registerAdminRPCRouter - registers RPC methods for service status, // stop and restart commands. func registerAdminRPCRouter(mux *router.Router) error { diff --git a/cmd/globals.go b/cmd/globals.go index 8b9f312cb..2fe707ba0 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -124,9 +124,13 @@ var ( // Global server's network statistics globalConnStats = newConnStats() + // Global HTTP request statisitics globalHTTPStats = newHTTPStats() + // Time when object layer was initialized on start up. + globalBootTime time.Time + // Add new variable global values here. ) diff --git a/cmd/server-main.go b/cmd/server-main.go index 3164c5783..3d6602604 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -25,6 +25,7 @@ import ( "sort" "strconv" "strings" + "time" "runtime" @@ -465,6 +466,9 @@ func serverMain(c *cli.Context) { globalObjectAPI = newObject globalObjLayerMutex.Unlock() + // Set startup time + globalBootTime = time.Now().UTC() + // Prints the formatted startup message once object layer is initialized. printStartupMessage(apiEndPoints) diff --git a/pkg/madmin/service-commands.go b/pkg/madmin/service-commands.go index 37869cd6e..2556a8960 100644 --- a/pkg/madmin/service-commands.go +++ b/pkg/madmin/service-commands.go @@ -25,6 +25,7 @@ import ( "io/ioutil" "net/http" "net/url" + "time" ) // BackendType - represents different backend types. @@ -70,6 +71,7 @@ type ServerVersion struct { type ServiceStatusMetadata struct { StorageInfo StorageInfo `json:"storageInfo"` ServerVersion ServerVersion `json:"serverVersion"` + Uptime time.Duration `json:"uptime"` } // ServiceStatus - Connect to a minio server and call Service Status Management API From 0c7694894b8627cbd551da0628a2e0752f47d175 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Wed, 8 Feb 2017 14:21:08 +0530 Subject: [PATCH 53/75] Added spaces for formatting (#3717) --- docs/bucket/notifications/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/bucket/notifications/README.md b/docs/bucket/notifications/README.md index 7e49aef75..82e299342 100644 --- a/docs/bucket/notifications/README.md +++ b/docs/bucket/notifications/README.md @@ -503,11 +503,15 @@ mc mb myminio/images mc mb myminio/images-thumbnail mc events add myminio/images arn:minio:sqs:us-east-1:1:webhook — events put — suffix .jpg ``` + Check if event notification is successfully configured by + ``` mc events list myminio/images ``` + You should get a response like this + ``` arn:minio:sqs:us-east-1:1:webhook s3:ObjectCreated:* Filter: suffix=".jpg" ``` From e5773e11c670a70264434c7837f30dd2106ad961 Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Thu, 9 Feb 2017 11:57:35 +0530 Subject: [PATCH 54/75] Make minio server compile on OpenBSD, NetBSD, Solaris (#3719) --- buildscripts/checkdeps.sh | 4 +- cmd/globals.go | 2 + cmd/posix-list-dir-nix.go | 2 +- cmd/posix-list-dir-others.go | 2 +- cmd/posix-utils_nix.go | 4 +- cmd/posix.go | 11 +- cmd/server-rlimit-nix.go | 2 +- cmd/server-rlimit-openbsd.go | 83 ++++++ pkg/disk/disk.go | 8 + pkg/disk/disk_test.go | 4 +- pkg/disk/{stat_nix.go => stat_bsd.go} | 9 +- pkg/disk/stat_fallback.go | 24 ++ pkg/disk/stat_linux.go | 39 +++ pkg/disk/stat_openbsd.go | 39 +++ pkg/disk/{type_unix.go => type_bsd.go} | 28 +- pkg/disk/type_darwin.go | 18 +- pkg/disk/type_linux.go | 20 +- pkg/lock/lock_solaris.go | 83 ++++++ vendor/github.com/fatih/color/README.md | 25 +- vendor/github.com/fatih/color/color.go | 244 +++++++++++++----- vendor/github.com/fatih/color/doc.go | 14 + .../mattn/go-isatty/isatty_appengine.go | 9 + .../github.com/mattn/go-isatty/isatty_bsd.go | 2 +- vendor/vendor.json | 10 +- 24 files changed, 545 insertions(+), 141 deletions(-) create mode 100644 cmd/server-rlimit-openbsd.go rename pkg/disk/{stat_nix.go => stat_bsd.go} (85%) create mode 100644 pkg/disk/stat_fallback.go create mode 100644 pkg/disk/stat_linux.go create mode 100644 pkg/disk/stat_openbsd.go rename pkg/disk/{type_unix.go => type_bsd.go} (55%) create mode 100644 pkg/lock/lock_solaris.go create mode 100644 vendor/github.com/mattn/go-isatty/isatty_appengine.go diff --git a/buildscripts/checkdeps.sh b/buildscripts/checkdeps.sh index 057f17b9d..b83fdfa43 100644 --- a/buildscripts/checkdeps.sh +++ b/buildscripts/checkdeps.sh @@ -97,7 +97,7 @@ assert_is_supported_arch() { assert_is_supported_os() { case "${KNAME}" in - Linux | FreeBSD ) + Linux | FreeBSD | OpenBSD | NetBSD | DragonFly ) return ;; Darwin ) @@ -113,7 +113,7 @@ assert_is_supported_os() { *) echo "ERROR" echo "OS '${KNAME}' is not supported." - echo "Supported OS: [Linux, FreeBSD, Darwin]" + echo "Supported OS: [Linux, FreeBSD, OpenBSD, NetBSD, Darwin, DragonFly]" exit 1 esac } diff --git a/cmd/globals.go b/cmd/globals.go index 2fe707ba0..f143d531c 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -51,6 +51,8 @@ const ( globalMinioDefaultOwnerID = "minio" globalMinioDefaultStorageClass = "STANDARD" globalWindowsOSName = "windows" + globalNetBSDOSName = "netbsd" + globalSolarisOSName = "solaris" // Add new global values here. ) diff --git a/cmd/posix-list-dir-nix.go b/cmd/posix-list-dir-nix.go index 1da7eaf76..4e2025b86 100644 --- a/cmd/posix-list-dir-nix.go +++ b/cmd/posix-list-dir-nix.go @@ -1,4 +1,4 @@ -// +build linux darwin dragonfly freebsd netbsd openbsd +// +build linux darwin freebsd netbsd openbsd /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/cmd/posix-list-dir-others.go b/cmd/posix-list-dir-others.go index dd40faca5..3cc2ec246 100644 --- a/cmd/posix-list-dir-others.go +++ b/cmd/posix-list-dir-others.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin,!openbsd,!freebsd,!netbsd,!dragonfly +// +build !linux,!darwin,!openbsd,!freebsd,!netbsd /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/cmd/posix-utils_nix.go b/cmd/posix-utils_nix.go index ebb59ad61..9b4fa5952 100644 --- a/cmd/posix-utils_nix.go +++ b/cmd/posix-utils_nix.go @@ -1,7 +1,7 @@ -// +build linux darwin dragonfly freebsd netbsd openbsd +// +build linux darwin dragonfly freebsd netbsd openbsd solaris /* - * Minio Cloud Storage, (C) 2016 Minio, Inc. + * Minio Cloud Storage, (C) 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/cmd/posix.go b/cmd/posix.go index 0a1969fda..89d1c77ed 100644 --- a/cmd/posix.go +++ b/cmd/posix.go @@ -153,11 +153,20 @@ func getDiskInfo(diskPath string) (di disk.Info, err error) { return di, err } +// List of operating systems where we ignore disk space +// verification. +var ignoreDiskFreeOS = []string{ + globalWindowsOSName, + globalNetBSDOSName, + globalSolarisOSName, +} + // checkDiskFree verifies if disk path has sufficient minimum free disk space and files. func (s *posix) checkDiskFree() (err error) { // We don't validate disk space or inode utilization on windows. // Each windows calls to 'GetVolumeInformationW' takes around 3-5seconds. - if runtime.GOOS == globalWindowsOSName { + // And StatFS is not supported by Go for solaris and netbsd. + if contains(ignoreDiskFreeOS, runtime.GOOS) { return nil } diff --git a/cmd/server-rlimit-nix.go b/cmd/server-rlimit-nix.go index 9c0b73f00..03341a6b1 100644 --- a/cmd/server-rlimit-nix.go +++ b/cmd/server-rlimit-nix.go @@ -1,4 +1,4 @@ -// +build !windows,!plan9 +// +build !windows,!plan9,!openbsd /* * Minio Cloud Storage, (C) 2016 Minio, Inc. diff --git a/cmd/server-rlimit-openbsd.go b/cmd/server-rlimit-openbsd.go new file mode 100644 index 000000000..16030447e --- /dev/null +++ b/cmd/server-rlimit-openbsd.go @@ -0,0 +1,83 @@ +// +build openbsd + +/* + * Minio Cloud Storage, (C) 2017 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 cmd + +import ( + "syscall" + + "github.com/minio/minio/pkg/sys" +) + +// For all unixes we need to bump allowed number of open files to a +// higher value than its usual default of '1024'. The reasoning is +// that this value is too small for a server. +func setMaxOpenFiles() error { + var rLimit syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + return err + } + // Set the current limit to Max, it is usually around 4096. + // TO increase this limit further user has to manually edit + // `/etc/security/limits.conf` + rLimit.Cur = rLimit.Max + return syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) +} + +// Set max memory used by minio as a process, this value is usually +// set to 'unlimited' but we need to validate additionally to verify +// if any hard limit is set by the user, in such a scenario would need +// to reset the global max cache size to be 80% of the hardlimit set +// by the user. This is done to honor the system limits and not crash. +func setMaxMemory() error { + var rLimit syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_DATA, &rLimit) + if err != nil { + return err + } + // Set the current limit to Max, it is default 'unlimited'. + // TO decrease this limit further user has to manually edit + // `/etc/security/limits.conf` + rLimit.Cur = rLimit.Max + err = syscall.Setrlimit(syscall.RLIMIT_DATA, &rLimit) + if err != nil { + return err + } + err = syscall.Getrlimit(syscall.RLIMIT_DATA, &rLimit) + if err != nil { + return err + } + // Validate if rlimit memory is set to lower + // than max cache size. Then we should use such value. + if uint64(rLimit.Cur) < globalMaxCacheSize { + globalMaxCacheSize = uint64(float64(50*rLimit.Cur) / 100) + } + + // Make sure globalMaxCacheSize is less than RAM size. + stats, err := sys.GetStats() + if err != nil && err != sys.ErrNotImplemented { + return err + } + // If TotalRAM is >= minRAMSize we proceed to enable cache. + // cache is always 50% of the totalRAM. + if err == nil && stats.TotalRAM >= minRAMSize { + globalMaxCacheSize = uint64(float64(50*stats.TotalRAM) / 100) + } + return nil +} diff --git a/pkg/disk/disk.go b/pkg/disk/disk.go index 4eae7c211..8b4265c39 100644 --- a/pkg/disk/disk.go +++ b/pkg/disk/disk.go @@ -27,3 +27,11 @@ type Info struct { Ffree int64 FSType string } + +func b2s(bs []int8) string { + b := make([]byte, len(bs)) + for i, v := range bs { + b[i] = byte(v) + } + return string(b) +} diff --git a/pkg/disk/disk_test.go b/pkg/disk/disk_test.go index 58858a4ff..a1a4915b1 100644 --- a/pkg/disk/disk_test.go +++ b/pkg/disk/disk_test.go @@ -1,5 +1,7 @@ +// +build !netbsd,!solaris + /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2015, 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/pkg/disk/stat_nix.go b/pkg/disk/stat_bsd.go similarity index 85% rename from pkg/disk/stat_nix.go rename to pkg/disk/stat_bsd.go index 1c1a58a01..31aebd521 100644 --- a/pkg/disk/stat_nix.go +++ b/pkg/disk/stat_bsd.go @@ -1,7 +1,7 @@ -// +build darwin dragonfly freebsd linux netbsd openbsd +// +build darwin freebsd dragonfly /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2015, 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,9 +34,6 @@ func GetInfo(path string) (info Info, err error) { info.Free = int64(s.Bsize) * int64(s.Bavail) info.Files = int64(s.Files) info.Ffree = int64(s.Ffree) - info.FSType, err = getFSType(path) - if err != nil { - return Info{}, err - } + info.FSType = getFSType(s.Fstypename) return info, nil } diff --git a/pkg/disk/stat_fallback.go b/pkg/disk/stat_fallback.go new file mode 100644 index 000000000..7439135bb --- /dev/null +++ b/pkg/disk/stat_fallback.go @@ -0,0 +1,24 @@ +// +build netbsd solaris + +/* + * Minio Cloud Storage, (C) 2017 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 disk + +// GetInfo returns total and free bytes available in a directory, e.g. `/`. +func GetInfo(path string) (info Info, err error) { + return Info{}, nil +} diff --git a/pkg/disk/stat_linux.go b/pkg/disk/stat_linux.go new file mode 100644 index 000000000..4106cd985 --- /dev/null +++ b/pkg/disk/stat_linux.go @@ -0,0 +1,39 @@ +// +build linux + +/* + * Minio Cloud Storage, (C) 2015, 2016, 2017 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 disk + +import ( + "syscall" +) + +// GetInfo returns total and free bytes available in a directory, e.g. `/`. +func GetInfo(path string) (info Info, err error) { + s := syscall.Statfs_t{} + err = syscall.Statfs(path, &s) + if err != nil { + return Info{}, err + } + info = Info{} + info.Total = int64(s.Bsize) * int64(s.Blocks) + info.Free = int64(s.Bsize) * int64(s.Bavail) + info.Files = int64(s.Files) + info.Ffree = int64(s.Ffree) + info.FSType = getFSType(int64(s.Type)) + return info, nil +} diff --git a/pkg/disk/stat_openbsd.go b/pkg/disk/stat_openbsd.go new file mode 100644 index 000000000..3a8d43218 --- /dev/null +++ b/pkg/disk/stat_openbsd.go @@ -0,0 +1,39 @@ +// +build openbsd + +/* + * Minio Cloud Storage, (C) 2017 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 disk + +import ( + "syscall" +) + +// GetInfo returns total and free bytes available in a directory, e.g. `/`. +func GetInfo(path string) (info Info, err error) { + s := syscall.Statfs_t{} + err = syscall.Statfs(path, &s) + if err != nil { + return Info{}, err + } + info = Info{} + info.Total = int64(s.F_bsize) * int64(s.F_blocks) + info.Free = int64(s.F_bsize) * int64(s.F_bavail) + info.Files = int64(s.F_files) + info.Ffree = int64(s.F_ffree) + info.FSType = getFSType(s.F_fstypename) + return info, nil +} diff --git a/pkg/disk/type_unix.go b/pkg/disk/type_bsd.go similarity index 55% rename from pkg/disk/type_unix.go rename to pkg/disk/type_bsd.go index 3fe4cafb2..0818f10d6 100644 --- a/pkg/disk/type_unix.go +++ b/pkg/disk/type_bsd.go @@ -1,7 +1,7 @@ -// +build freebsd +// +build darwin freebsd dragonfly openbsd /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,27 +18,7 @@ package disk -import ( - "strconv" - "syscall" -) - -// fsType2StringMap - list of filesystems supported by donut on linux -var fsType2StringMap = map[string]string{ - "35": "UFS", -} - // getFSType returns the filesystem type of the underlying mounted filesystem -func getFSType(path string) (string, error) { - s := syscall.Statfs_t{} - err := syscall.Statfs(path, &s) - if err != nil { - return "", err - } - fsTypeHex := strconv.FormatInt(int64(s.Type), 16) - fsTypeString, ok := fsType2StringMap[fsTypeHex] - if ok == false { - return "UNKNOWN", nil - } - return fsTypeString, nil +func getFSType(fstype [16]int8) string { + return b2s(fstype[:]) } diff --git a/pkg/disk/type_darwin.go b/pkg/disk/type_darwin.go index c000e1a08..85cad1aa7 100644 --- a/pkg/disk/type_darwin.go +++ b/pkg/disk/type_darwin.go @@ -18,10 +18,7 @@ package disk -import ( - "strconv" - "syscall" -) +import "strconv" // fsType2StrinMap - list of filesystems supported by donut var fsType2StringMap = map[string]string{ @@ -29,16 +26,11 @@ var fsType2StringMap = map[string]string{ } // getFSType returns the filesystem type of the underlying mounted filesystem -func getFSType(path string) (string, error) { - s := syscall.Statfs_t{} - err := syscall.Statfs(path, &s) - if err != nil { - return "", err - } - fsTypeHex := strconv.FormatUint(uint64(s.Type), 16) +func getFSType(ftype int64) string { + fsTypeHex := strconv.FormatInt(ftype, 16) fsTypeString, ok := fsType2StringMap[fsTypeHex] if !ok { - return "UNKNOWN", nil + return "UNKNOWN" } - return fsTypeString, nil + return fsTypeString } diff --git a/pkg/disk/type_linux.go b/pkg/disk/type_linux.go index 4609c90b0..98dceb66f 100644 --- a/pkg/disk/type_linux.go +++ b/pkg/disk/type_linux.go @@ -1,7 +1,7 @@ // +build linux /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,7 @@ package disk -import ( - "strconv" - "syscall" -) +import "strconv" // fsType2StringMap - list of filesystems supported by donut on linux var fsType2StringMap = map[string]string{ @@ -40,16 +37,11 @@ var fsType2StringMap = map[string]string{ } // getFSType returns the filesystem type of the underlying mounted filesystem -func getFSType(path string) (string, error) { - s := syscall.Statfs_t{} - err := syscall.Statfs(path, &s) - if err != nil { - return "", err - } - fsTypeHex := strconv.FormatInt(int64(s.Type), 16) +func getFSType(ftype int64) string { + fsTypeHex := strconv.FormatInt(ftype, 16) fsTypeString, ok := fsType2StringMap[fsTypeHex] if ok == false { - return "UNKNOWN", nil + return "UNKNOWN" } - return fsTypeString, nil + return fsTypeString } diff --git a/pkg/lock/lock_solaris.go b/pkg/lock/lock_solaris.go new file mode 100644 index 000000000..76aa769b6 --- /dev/null +++ b/pkg/lock/lock_solaris.go @@ -0,0 +1,83 @@ +// +build solaris + +/* + * Minio Cloud Storage, (C) 2017 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 lock + +import ( + "fmt" + "os" + "syscall" +) + +// LockedOpenFile - initializes a new lock and protects +// the file from concurrent access across mount points. +// This implementation doesn't support all the open +// flags and shouldn't be considered as replacement +// for os.OpenFile(). +func LockedOpenFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { + var lock syscall.Flock_t + lock.Start = 0 + lock.Len = 0 + lock.Pid = 0 + + var lockType int16 + switch flag { + case syscall.O_RDONLY: + lockType = syscall.F_RDLCK + case syscall.O_WRONLY: + fallthrough + case syscall.O_RDWR: + fallthrough + case syscall.O_WRONLY | syscall.O_CREAT: + fallthrough + case syscall.O_RDWR | syscall.O_CREAT: + lockType = syscall.F_WRLCK + default: + return nil, fmt.Errorf("Unsupported flag (%d)", flag) + } + + lock.Type = lockType + lock.Whence = 0 + + f, err := os.OpenFile(path, flag, perm) + if err != nil { + return nil, err + } + + if err = syscall.FcntlFlock(f.Fd(), syscall.F_SETLKW, &lock); err != nil { + f.Close() + return nil, err + } + + st, err := os.Stat(path) + if err != nil { + f.Close() + return nil, err + } + + if st.IsDir() { + f.Close() + return nil, &os.PathError{ + Op: "open", + Path: path, + Err: syscall.EISDIR, + } + } + + return &LockedFile{f}, nil +} diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md index 0921f98a5..25abbca3f 100644 --- a/vendor/github.com/fatih/color/README.md +++ b/vendor/github.com/fatih/color/README.md @@ -56,6 +56,16 @@ whiteBackground := red.Add(color.BgWhite) whiteBackground.Println("Red text with white background.") ``` +### Use your own output (io.Writer) + +```go +// Use your own io.Writer output +color.New(color.FgBlue).Fprintln(myWriter, "blue color!") + +blue := color.New(color.FgBlue) +blue.Fprint(writer, "This will print text in blue.") +``` + ### Custom print functions (PrintFunc) ```go @@ -69,6 +79,17 @@ notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() notice("Don't forget this...") ``` +### Custom fprint functions (FprintFunc) + +```go +blue := color.New(FgBlue).FprintfFunc() +blue(myWriter, "important notice: %s", stars) + +// Mix up with multiple attributes +success := color.New(color.Bold, color.FgGreen).FprintlnFunc() +success(myWriter, "Don't forget this...") +``` + ### Insert into noncolor strings (SprintFunc) ```go @@ -81,8 +102,8 @@ info := color.New(color.FgWhite, color.BgGreen).SprintFunc() fmt.Printf("This %s rocks!\n", info("package")) // Use helper functions -fmt.Printf("This", color.RedString("warning"), "should be not neglected.") -fmt.Printf(color.GreenString("Info:"), "an important message." ) +fmt.Println("This", color.RedString("warning"), "should be not neglected.") +fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.") // Windows supported too! Just don't forget to change the output to color.Output fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go index e3e997284..dba8f211e 100644 --- a/vendor/github.com/fatih/color/color.go +++ b/vendor/github.com/fatih/color/color.go @@ -2,19 +2,32 @@ package color import ( "fmt" + "io" "os" "strconv" "strings" + "sync" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" ) -// NoColor defines if the output is colorized or not. It's dynamically set to -// false or true based on the stdout's file descriptor referring to a terminal -// or not. This is a global option and affects all colors. For more control -// over each color block use the methods DisableColor() individually. -var NoColor = !isatty.IsTerminal(os.Stdout.Fd()) +var ( + // NoColor defines if the output is colorized or not. It's dynamically set to + // false or true based on the stdout's file descriptor referring to a terminal + // or not. This is a global option and affects all colors. For more control + // over each color block use the methods DisableColor() individually. + NoColor = !isatty.IsTerminal(os.Stdout.Fd()) || os.Getenv("TERM") == "dumb" + + // Output defines the standard output of the print functions. By default + // os.Stdout is used. + Output = colorable.NewColorableStdout() + + // colorsCache is used to reduce the count of created Color objects and + // allows to reuse already created objects with required Attribute. + colorsCache = make(map[Attribute]*Color) + colorsCacheMu sync.Mutex // protects colorsCache +) // Color defines a custom color object which is defined by SGR parameters. type Color struct { @@ -132,6 +145,27 @@ func (c *Color) unset() { Unset() } +func (c *Color) setWriter(w io.Writer) *Color { + if c.isNoColorSet() { + return c + } + + fmt.Fprintf(w, c.format()) + return c +} + +func (c *Color) unsetWriter(w io.Writer) { + if c.isNoColorSet() { + return + } + + if NoColor { + return + } + + fmt.Fprintf(w, "%s[%dm", escape, Reset) +} + // Add is used to chain SGR parameters. Use as many as parameters to combine // and create custom color objects. Example: Add(color.FgRed, color.Underline). func (c *Color) Add(value ...Attribute) *Color { @@ -145,9 +179,17 @@ func (c *Color) prepend(value Attribute) { c.params[0] = value } -// Output defines the standard output of the print functions. By default -// os.Stdout is used. -var Output = colorable.NewColorableStdout() +// Fprint formats using the default formats for its operands and writes to w. +// Spaces are added between operands when neither is a string. +// It returns the number of bytes written and any write error encountered. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + c.setWriter(w) + defer c.unsetWriter(w) + + return fmt.Fprint(w, a...) +} // Print formats using the default formats for its operands and writes to // standard output. Spaces are added between operands when neither is a @@ -161,6 +203,17 @@ func (c *Color) Print(a ...interface{}) (n int, err error) { return fmt.Fprint(Output, a...) } +// Fprintf formats according to a format specifier and writes to w. +// It returns the number of bytes written and any write error encountered. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + c.setWriter(w) + defer c.unsetWriter(w) + + return fmt.Fprintf(w, format, a...) +} + // Printf formats according to a format specifier and writes to standard output. // It returns the number of bytes written and any write error encountered. // This is the standard fmt.Printf() method wrapped with the given color. @@ -171,6 +224,17 @@ func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(Output, format, a...) } +// Fprintln formats using the default formats for its operands and writes to w. +// Spaces are always added between operands and a newline is appended. +// On Windows, users should wrap w with colorable.NewColorable() if w is of +// type *os.File. +func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + c.setWriter(w) + defer c.unsetWriter(w) + + return fmt.Fprintln(w, a...) +} + // Println formats using the default formats for its operands and writes to // standard output. Spaces are always added between operands and a newline is // appended. It returns the number of bytes written and any write error @@ -183,27 +247,57 @@ func (c *Color) Println(a ...interface{}) (n int, err error) { return fmt.Fprintln(Output, a...) } +// FprintFunc returns a new function that prints the passed arguments as +// colorized with color.Fprint(). +func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) { + return func(w io.Writer, a ...interface{}) { + c.Fprint(w, a...) + } +} + // PrintFunc returns a new function that prints the passed arguments as // colorized with color.Print(). func (c *Color) PrintFunc() func(a ...interface{}) { - return func(a ...interface{}) { c.Print(a...) } + return func(a ...interface{}) { + c.Print(a...) + } +} + +// FprintfFunc returns a new function that prints the passed arguments as +// colorized with color.Fprintf(). +func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) { + return func(w io.Writer, format string, a ...interface{}) { + c.Fprintf(w, format, a...) + } } // PrintfFunc returns a new function that prints the passed arguments as // colorized with color.Printf(). func (c *Color) PrintfFunc() func(format string, a ...interface{}) { - return func(format string, a ...interface{}) { c.Printf(format, a...) } + return func(format string, a ...interface{}) { + c.Printf(format, a...) + } +} + +// FprintlnFunc returns a new function that prints the passed arguments as +// colorized with color.Fprintln(). +func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) { + return func(w io.Writer, a ...interface{}) { + c.Fprintln(w, a...) + } } // PrintlnFunc returns a new function that prints the passed arguments as // colorized with color.Println(). func (c *Color) PrintlnFunc() func(a ...interface{}) { - return func(a ...interface{}) { c.Println(a...) } + return func(a ...interface{}) { + c.Println(a...) + } } // SprintFunc returns a new function that returns colorized strings for the // given arguments with fmt.Sprint(). Useful to put into or mix into other -// string. Windows users should use this in conjuction with color.Output, example: +// string. Windows users should use this in conjunction with color.Output, example: // // put := New(FgYellow).SprintFunc() // fmt.Fprintf(color.Output, "This is a %s", put("warning")) @@ -215,7 +309,7 @@ func (c *Color) SprintFunc() func(a ...interface{}) string { // SprintfFunc returns a new function that returns colorized strings for the // given arguments with fmt.Sprintf(). Useful to put into or mix into other -// string. Windows users should use this in conjuction with color.Output. +// string. Windows users should use this in conjunction with color.Output. func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { return func(format string, a ...interface{}) string { return c.wrap(fmt.Sprintf(format, a...)) @@ -224,7 +318,7 @@ func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { // SprintlnFunc returns a new function that returns colorized strings for the // given arguments with fmt.Sprintln(). Useful to put into or mix into other -// string. Windows users should use this in conjuction with color.Output. +// string. Windows users should use this in conjunction with color.Output. func (c *Color) SprintlnFunc() func(a ...interface{}) string { return func(a ...interface{}) string { return c.wrap(fmt.Sprintln(a...)) @@ -267,7 +361,7 @@ func (c *Color) DisableColor() { c.noColor = boolPtr(true) } -// EnableColor enables the color output. Use it in conjuction with +// EnableColor enables the color output. Use it in conjunction with // DisableColor(). Otherwise this method has no side effects. func (c *Color) EnableColor() { c.noColor = boolPtr(false) @@ -312,91 +406,105 @@ func boolPtr(v bool) *bool { return &v } -// Black is an convenient helper function to print with black foreground. A -// newline is appended to format by default. -func Black(format string, a ...interface{}) { printColor(format, FgBlack, a...) } +func getCachedColor(p Attribute) *Color { + colorsCacheMu.Lock() + defer colorsCacheMu.Unlock() -// Red is an convenient helper function to print with red foreground. A -// newline is appended to format by default. -func Red(format string, a ...interface{}) { printColor(format, FgRed, a...) } + c, ok := colorsCache[p] + if !ok { + c = New(p) + colorsCache[p] = c + } -// Green is an convenient helper function to print with green foreground. A -// newline is appended to format by default. -func Green(format string, a ...interface{}) { printColor(format, FgGreen, a...) } + return c +} -// Yellow is an convenient helper function to print with yellow foreground. -// A newline is appended to format by default. -func Yellow(format string, a ...interface{}) { printColor(format, FgYellow, a...) } +func colorPrint(format string, p Attribute, a ...interface{}) { + c := getCachedColor(p) -// Blue is an convenient helper function to print with blue foreground. A -// newline is appended to format by default. -func Blue(format string, a ...interface{}) { printColor(format, FgBlue, a...) } - -// Magenta is an convenient helper function to print with magenta foreground. -// A newline is appended to format by default. -func Magenta(format string, a ...interface{}) { printColor(format, FgMagenta, a...) } - -// Cyan is an convenient helper function to print with cyan foreground. A -// newline is appended to format by default. -func Cyan(format string, a ...interface{}) { printColor(format, FgCyan, a...) } - -// White is an convenient helper function to print with white foreground. A -// newline is appended to format by default. -func White(format string, a ...interface{}) { printColor(format, FgWhite, a...) } - -func printColor(format string, p Attribute, a ...interface{}) { if !strings.HasSuffix(format, "\n") { format += "\n" } - c := &Color{params: []Attribute{p}} - c.Printf(format, a...) + if len(a) == 0 { + c.Print(format) + } else { + c.Printf(format, a...) + } } +func colorString(format string, p Attribute, a ...interface{}) string { + c := getCachedColor(p) + + if len(a) == 0 { + return c.SprintFunc()(format) + } + + return c.SprintfFunc()(format, a...) +} + +// Black is an convenient helper function to print with black foreground. A +// newline is appended to format by default. +func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) } + +// Red is an convenient helper function to print with red foreground. A +// newline is appended to format by default. +func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) } + +// Green is an convenient helper function to print with green foreground. A +// newline is appended to format by default. +func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) } + +// Yellow is an convenient helper function to print with yellow foreground. +// A newline is appended to format by default. +func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) } + +// Blue is an convenient helper function to print with blue foreground. A +// newline is appended to format by default. +func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) } + +// Magenta is an convenient helper function to print with magenta foreground. +// A newline is appended to format by default. +func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) } + +// Cyan is an convenient helper function to print with cyan foreground. A +// newline is appended to format by default. +func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) } + +// White is an convenient helper function to print with white foreground. A +// newline is appended to format by default. +func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) } + // BlackString is an convenient helper function to return a string with black // foreground. -func BlackString(format string, a ...interface{}) string { - return New(FgBlack).SprintfFunc()(format, a...) -} +func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) } // RedString is an convenient helper function to return a string with red // foreground. -func RedString(format string, a ...interface{}) string { - return New(FgRed).SprintfFunc()(format, a...) -} +func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) } // GreenString is an convenient helper function to return a string with green // foreground. -func GreenString(format string, a ...interface{}) string { - return New(FgGreen).SprintfFunc()(format, a...) -} +func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) } // YellowString is an convenient helper function to return a string with yellow // foreground. -func YellowString(format string, a ...interface{}) string { - return New(FgYellow).SprintfFunc()(format, a...) -} +func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) } // BlueString is an convenient helper function to return a string with blue // foreground. -func BlueString(format string, a ...interface{}) string { - return New(FgBlue).SprintfFunc()(format, a...) -} +func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) } // MagentaString is an convenient helper function to return a string with magenta // foreground. func MagentaString(format string, a ...interface{}) string { - return New(FgMagenta).SprintfFunc()(format, a...) + return colorString(format, FgMagenta, a...) } // CyanString is an convenient helper function to return a string with cyan // foreground. -func CyanString(format string, a ...interface{}) string { - return New(FgCyan).SprintfFunc()(format, a...) -} +func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) } // WhiteString is an convenient helper function to return a string with white // foreground. -func WhiteString(format string, a ...interface{}) string { - return New(FgWhite).SprintfFunc()(format, a...) -} +func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) } diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go index 17908787c..1e57812d7 100644 --- a/vendor/github.com/fatih/color/doc.go +++ b/vendor/github.com/fatih/color/doc.go @@ -37,6 +37,11 @@ separate color object. whiteBackground := red.Add(color.BgWhite) whiteBackground.Println("Red text with White background.") + // Use your own io.Writer output + color.New(color.FgBlue).Fprintln(myWriter, "blue color!") + + blue := color.New(color.FgBlue) + blue.Fprint(myWriter, "This will print text in blue.") You can create PrintXxx functions to simplify even more: @@ -49,6 +54,15 @@ You can create PrintXxx functions to simplify even more: notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() notice("don't forget this...") +You can also FprintXxx functions to pass your own io.Writer: + + blue := color.New(FgBlue).FprintfFunc() + blue(myWriter, "important notice: %s", stars) + + // Mix up with multiple attributes + success := color.New(color.Bold, color.FgGreen).FprintlnFunc() + success(myWriter, don't forget this...") + Or create SprintXxx functions to mix strings with other non-colorized strings: diff --git a/vendor/github.com/mattn/go-isatty/isatty_appengine.go b/vendor/github.com/mattn/go-isatty/isatty_appengine.go new file mode 100644 index 000000000..83c588773 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_appengine.go @@ -0,0 +1,9 @@ +// +build appengine + +package isatty + +// IsTerminal returns true if the file descriptor is terminal which +// is always false on on appengine classic which is a sandboxed PaaS. +func IsTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go index 98ffe86a4..42f2514d1 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -1,4 +1,4 @@ -// +build darwin freebsd openbsd netbsd +// +build darwin freebsd openbsd netbsd dragonfly // +build !appengine package isatty diff --git a/vendor/vendor.json b/vendor/vendor.json index 87783717c..ef5b851e1 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -57,9 +57,10 @@ "revisionTime": "2015-12-24T06:54:52+02:00" }, { + "checksumSHA1": "XEBl9iQQvfXNlwCSzyAOCqAlYEA=", "path": "github.com/fatih/color", - "revision": "87d4004f2ab62d0d255e0a38f1680aa534549fe3", - "revisionTime": "2016-06-10T14:06:02+03:00" + "revision": "42c364ba490082e4815b5222728711b3440603eb", + "revisionTime": "2017-01-13T15:16:12Z" }, { "checksumSHA1": "3yco0089CSJ4qbyUccpbDC2+dPg=", @@ -150,9 +151,10 @@ "revisionTime": "2016-06-03T00:08:27+09:00" }, { + "checksumSHA1": "xZuhljnmBysJPta/lMyYmJdujCg=", "path": "github.com/mattn/go-isatty", - "revision": "56b76bdf51f7708750eac80fa38b952bb9f32639", - "revisionTime": "2015-12-11T09:06:21+09:00" + "revision": "30a891c33c7cde7b02a981314b4228ec99380cca", + "revisionTime": "2016-11-23T14:36:37Z" }, { "checksumSHA1": "4gphCNVXIjp5ytz3+S3SD3Dp948=", From 6800902b43b208e1dfe619a4b53a000e58630938 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Wed, 8 Feb 2017 23:39:08 -0800 Subject: [PATCH 55/75] web-handlers: Implement API to download files as a zip file. (#3715) --- cmd/web-handlers.go | 86 +++++++++++++++++++++++++++++++++++++++ cmd/web-handlers_test.go | 88 ++++++++++++++++++++++++++++++++++++++++ cmd/web-router.go | 1 + 3 files changed, 175 insertions(+) diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 53daca3cc..e11743e94 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -17,6 +17,7 @@ package cmd import ( + "archive/zip" "encoding/json" "errors" "fmt" @@ -530,6 +531,91 @@ func (web *webAPIHandlers) Download(w http.ResponseWriter, r *http.Request) { } } +// DownloadZipArgs - Argument for downloading a bunch of files as a zip file. +// JSON will look like: +// '{"bucketname":"testbucket","prefix":"john/pics/","objects":["hawaii/","maldives/","sanjose.jpg"]}' +type DownloadZipArgs struct { + Objects []string `json:"objects"` // can be files or sub-directories + Prefix string `json:"prefix"` // current directory in the browser-ui + BucketName string `json:"bucketname"` // bucket name. +} + +// Takes a list of objects and creates a zip file that sent as the response body. +func (web *webAPIHandlers) DownloadZip(w http.ResponseWriter, r *http.Request) { + objectAPI := web.ObjectAPI() + if objectAPI == nil { + writeWebErrorResponse(w, errServerNotInitialized) + return + } + + token := r.URL.Query().Get("token") + + if !isAuthTokenValid(token) { + writeWebErrorResponse(w, errAuthentication) + return + } + var args DownloadZipArgs + decodeErr := json.NewDecoder(r.Body).Decode(&args) + if decodeErr != nil { + writeWebErrorResponse(w, decodeErr) + return + } + + archive := zip.NewWriter(w) + defer archive.Close() + + for _, object := range args.Objects { + // Writes compressed object file to the response. + zipit := func(objectName string) error { + info, err := objectAPI.GetObjectInfo(args.BucketName, objectName) + if err != nil { + return err + } + header := &zip.FileHeader{ + Name: strings.TrimPrefix(objectName, args.Prefix), + Method: zip.Deflate, + UncompressedSize64: uint64(info.Size), + UncompressedSize: uint32(info.Size), + } + writer, err := archive.CreateHeader(header) + if err != nil { + writeWebErrorResponse(w, errUnexpected) + return err + } + return objectAPI.GetObject(args.BucketName, objectName, 0, info.Size, writer) + } + + if !strings.HasSuffix(object, "/") { + // If not a directory, compress the file and write it to response. + err := zipit(pathJoin(args.Prefix, object)) + if err != nil { + return + } + continue + } + + // For directories, list the contents recursively and write the objects as compressed + // date to the response writer. + marker := "" + for { + lo, err := objectAPI.ListObjects(args.BucketName, pathJoin(args.Prefix, object), marker, "", 1000) + if err != nil { + return + } + marker = lo.NextMarker + for _, obj := range lo.Objects { + err = zipit(obj.Name) + if err != nil { + return + } + } + if !lo.IsTruncated { + break + } + } + } +} + // GetBucketPolicyArgs - get bucket policy args. type GetBucketPolicyArgs struct { BucketName string `json:"bucketName"` diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index ae0c2576a..66f7cbd52 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -17,9 +17,14 @@ package cmd import ( + "archive/zip" "bytes" + "crypto/md5" + "encoding/hex" + "encoding/json" "errors" "fmt" + "io" "io/ioutil" "net/http" "net/http/httptest" @@ -796,6 +801,89 @@ func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandl } } +// Test web.DownloadZip +func TestWebHandlerDownloadZip(t *testing.T) { + ExecObjectLayerTest(t, testWebHandlerDownloadZip) +} + +func testWebHandlerDownloadZip(obj ObjectLayer, instanceType string, t TestErrHandler) { + apiRouter := initTestWebRPCEndPoint(obj) + credentials := serverConfig.GetCredential() + + authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) + if err != nil { + t.Fatal("Cannot authenticate") + } + + bucket := getRandomBucketName() + fileOne := "aaaaaaaaaaaaaa" + fileTwo := "bbbbbbbbbbbbbb" + fileThree := "cccccccccccccc" + + // Create bucket. + err = obj.MakeBucket(bucket) + if err != nil { + // failed to create newbucket, abort. + t.Fatalf("%s : %s", instanceType, err) + } + + obj.PutObject(bucket, "a/one", int64(len(fileOne)), strings.NewReader(fileOne), nil, "") + obj.PutObject(bucket, "a/b/two", int64(len(fileTwo)), strings.NewReader(fileTwo), nil, "") + obj.PutObject(bucket, "a/c/three", int64(len(fileThree)), strings.NewReader(fileThree), nil, "") + + test := func(token string) (int, []byte) { + rec := httptest.NewRecorder() + path := "/minio/zip" + "?token=" + if token != "" { + path = path + token + } + args := DownloadZipArgs{ + Objects: []string{"one", "b/", "c/"}, + Prefix: "a/", + BucketName: bucket, + } + + var argsData []byte + argsData, err = json.Marshal(args) + if err != nil { + return 0, nil + } + var req *http.Request + req, err = http.NewRequest("GET", path, bytes.NewBuffer(argsData)) + + if err != nil { + t.Fatalf("Cannot create upload request, %v", err) + } + + apiRouter.ServeHTTP(rec, req) + return rec.Code, rec.Body.Bytes() + } + code, data := test("") + if code != 403 { + t.Fatal("Expected to receive authentication error") + } + code, data = test(authorization) + if code != 200 { + t.Fatal("web.DownloadsZip() failed") + } + reader, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + t.Fatal(err) + } + h := md5.New() + for _, file := range reader.File { + fileReader, err := file.Open() + if err != nil { + t.Fatal(err) + } + io.Copy(h, fileReader) + } + // Verify the md5 of the response. + if hex.EncodeToString(h.Sum(nil)) != "ac7196449b14bea42775d29e8bb29f50" { + t.Fatal("Incorrect zip contents") + } +} + // Wrapper for calling PresignedGet handler func TestWebHandlerPresignedGetHandler(t *testing.T) { ExecObjectLayerTest(t, testWebPresignedGetHandler) diff --git a/cmd/web-router.go b/cmd/web-router.go index f478abfb8..c4fdfbb2c 100644 --- a/cmd/web-router.go +++ b/cmd/web-router.go @@ -84,6 +84,7 @@ func registerWebRouter(mux *router.Router) error { webBrowserRouter.Methods("POST").Path("/webrpc").Handler(webRPC) webBrowserRouter.Methods("PUT").Path("/upload/{bucket}/{object:.+}").HandlerFunc(web.Upload) webBrowserRouter.Methods("GET").Path("/download/{bucket}/{object:.+}").Queries("token", "{token:.*}").HandlerFunc(web.Download) + webBrowserRouter.Methods("GET").Path("/zip").Queries("token", "{token:.*}").HandlerFunc(web.DownloadZip) // Add compression for assets. compressedAssets := handlers.CompressHandler(http.StripPrefix(reservedBucket, http.FileServer(assetFS()))) From c9b1468c3bf41630fbb1647b782d46257eb7ce1c Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Thu, 9 Feb 2017 21:37:32 +0100 Subject: [PATCH 56/75] Presigend Post: Error out when File is not found (#3723) Follow S3 behavior when no File is sent in the presigned post request form. --- cmd/api-errors.go | 6 ++++++ cmd/bucket-handlers.go | 6 ++++++ cmd/handler-utils.go | 11 +++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/api-errors.go b/cmd/api-errors.go index 656c6a39f..8eb82761a 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -83,6 +83,7 @@ const ( ErrInvalidPartOrder ErrAuthorizationHeaderMalformed ErrMalformedPOSTRequest + ErrPOSTFileRequired ErrSignatureVersionNotSupported ErrBucketNotEmpty ErrAllAccessDisabled @@ -333,6 +334,11 @@ var errorCodeResponse = map[APIErrorCode]APIError{ Description: "The body of your POST request is not well-formed multipart/form-data.", HTTPStatusCode: http.StatusBadRequest, }, + ErrPOSTFileRequired: { + Code: "InvalidArgument", + Description: "POST requires exactly one file upload per request.", + HTTPStatusCode: http.StatusBadRequest, + }, ErrSignatureVersionNotSupported: { Code: "InvalidRequest", Description: "The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.", diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 660396a3a..96a6971c0 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -428,6 +428,12 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h return } + // Check if file is provided, error out otherwise. + if fileBody == nil { + writeErrorResponse(w, ErrPOSTFileRequired, r.URL) + return + } + // Close multipart file defer fileBody.Close() diff --git a/cmd/handler-utils.go b/cmd/handler-utils.go index 7b03a7e83..3b0e852e1 100644 --- a/cmd/handler-utils.go +++ b/cmd/handler-utils.go @@ -167,7 +167,7 @@ func extractPostPolicyFormValues(form *multipart.Form) (filePart io.ReadCloser, canonicalFormName := http.CanonicalHeaderKey(k) // Check if value's field exceeds S3 limit if int64(len(v[0])) > maxFormFieldSize { - return nil, "", 0, nil, errSizeUnexpected + return nil, "", 0, nil, traceError(errSizeUnexpected) } // Set the form value formValues[canonicalFormName] = v[0] @@ -178,7 +178,7 @@ func extractPostPolicyFormValues(form *multipart.Form) (filePart io.ReadCloser, canonicalFormName := http.CanonicalHeaderKey(k) if canonicalFormName == "File" { if len(v) == 0 { - return nil, "", 0, nil, errInvalidArgument + return nil, "", 0, nil, traceError(errInvalidArgument) } // Fetch fileHeader which has the uploaded file information fileHeader := v[0] @@ -186,15 +186,18 @@ func extractPostPolicyFormValues(form *multipart.Form) (filePart io.ReadCloser, fileName = fileHeader.Filename // Open the uploaded part filePart, err = fileHeader.Open() + if err != nil { + return nil, "", 0, nil, traceError(err) + } // Compute file size fileSize, err = filePart.(io.Seeker).Seek(0, 2) if err != nil { - return nil, "", 0, nil, err + return nil, "", 0, nil, traceError(err) } // Reset Seek to the beginning _, err = filePart.(io.Seeker).Seek(0, 0) if err != nil { - return nil, "", 0, nil, err + return nil, "", 0, nil, traceError(err) } // File found and ready for reading break From f38222c0cce95783f62fd5b12d5822dd343b628e Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Fri, 10 Feb 2017 00:01:00 +0100 Subject: [PATCH 57/75] update the blake2b implementation (#3724) Fixes a performance bug caused by SSE-AVX register savings on amd64. --- cmd/erasure-utils.go | 6 +- .../github.com/minio/blake2b-simd/blake2b.go | 301 ---- .../minio/blake2b-simd/compressAvx2_amd64.go | 47 - .../minio/blake2b-simd/compressAvx2_amd64.s | 671 -------- .../minio/blake2b-simd/compressAvx_amd64.go | 41 - .../minio/blake2b-simd/compressAvx_amd64.s | 682 -------- .../minio/blake2b-simd/compressSse_amd64.go | 41 - .../minio/blake2b-simd/compressSse_amd64.s | 770 --------- .../minio/blake2b-simd/compress_amd64.go | 30 - .../minio/blake2b-simd/compress_generic.go | 1419 ----------------- .../minio/blake2b-simd/compress_noasm.go | 23 - vendor/github.com/minio/blake2b-simd/cpuid.go | 60 - .../github.com/minio/blake2b-simd/cpuid_386.s | 33 - .../minio/blake2b-simd/cpuid_amd64.s | 34 - vendor/golang.org/x/crypto/blake2b/blake2b.go | 194 +++ .../x/crypto/blake2b/blake2bAVX2_amd64.go | 43 + .../x/crypto/blake2b/blake2bAVX2_amd64.s | 762 +++++++++ .../x/crypto/blake2b/blake2b_amd64.go | 25 + .../x/crypto/blake2b/blake2b_amd64.s | 290 ++++ .../x/crypto/blake2b/blake2b_generic.go | 179 +++ .../x/crypto/blake2b/blake2b_ref.go | 11 + .../x/crypto/blake2b/blake2b_test.go | 448 ++++++ 22 files changed, 1955 insertions(+), 4155 deletions(-) delete mode 100644 vendor/github.com/minio/blake2b-simd/blake2b.go delete mode 100644 vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.go delete mode 100644 vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.s delete mode 100644 vendor/github.com/minio/blake2b-simd/compressAvx_amd64.go delete mode 100644 vendor/github.com/minio/blake2b-simd/compressAvx_amd64.s delete mode 100644 vendor/github.com/minio/blake2b-simd/compressSse_amd64.go delete mode 100644 vendor/github.com/minio/blake2b-simd/compressSse_amd64.s delete mode 100644 vendor/github.com/minio/blake2b-simd/compress_amd64.go delete mode 100644 vendor/github.com/minio/blake2b-simd/compress_generic.go delete mode 100644 vendor/github.com/minio/blake2b-simd/compress_noasm.go delete mode 100644 vendor/github.com/minio/blake2b-simd/cpuid.go delete mode 100644 vendor/github.com/minio/blake2b-simd/cpuid_386.s delete mode 100644 vendor/github.com/minio/blake2b-simd/cpuid_amd64.s create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_generic.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_ref.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_test.go diff --git a/cmd/erasure-utils.go b/cmd/erasure-utils.go index d01ea731a..814df1c47 100644 --- a/cmd/erasure-utils.go +++ b/cmd/erasure-utils.go @@ -24,8 +24,8 @@ import ( "sync" "github.com/klauspost/reedsolomon" - "github.com/minio/blake2b-simd" "github.com/minio/sha256-simd" + "golang.org/x/crypto/blake2b" ) // newHashWriters - inititialize a slice of hashes for the disk count. @@ -48,14 +48,14 @@ func newHash(algo string) (h hash.Hash) { // ignore the error, because New512 without a key never fails // New512 only returns a non-nil error, if the length of the passed // key > 64 bytes - but we use blake2b as hash function (no key) - h = blake2b.New512() + h, _ = blake2b.New512(nil) // Add new hashes here. default: // Default to blake2b. // ignore the error, because New512 without a key never fails // New512 only returns a non-nil error, if the length of the passed // key > 64 bytes - but we use blake2b as hash function (no key) - h = blake2b.New512() + h, _ = blake2b.New512(nil) } return h } diff --git a/vendor/github.com/minio/blake2b-simd/blake2b.go b/vendor/github.com/minio/blake2b-simd/blake2b.go deleted file mode 100644 index 538466a1a..000000000 --- a/vendor/github.com/minio/blake2b-simd/blake2b.go +++ /dev/null @@ -1,301 +0,0 @@ -// Written in 2012 by Dmitry Chestnykh. -// -// To the extent possible under law, the author have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. -// http://creativecommons.org/publicdomain/zero/1.0/ - -// Package blake2b implements BLAKE2b cryptographic hash function. -package blake2b - -import ( - "encoding/binary" - "errors" - "hash" -) - -const ( - BlockSize = 128 // block size of algorithm - Size = 64 // maximum digest size - SaltSize = 16 // maximum salt size - PersonSize = 16 // maximum personalization string size - KeySize = 64 // maximum size of key -) - -type digest struct { - h [8]uint64 // current chain value - t [2]uint64 // message bytes counter - f [2]uint64 // finalization flags - x [BlockSize]byte // buffer for data not yet compressed - nx int // number of bytes in buffer - - ih [8]uint64 // initial chain value (after config) - paddedKey [BlockSize]byte // copy of key, padded with zeros - isKeyed bool // indicates whether hash was keyed - size uint8 // digest size in bytes - isLastNode bool // indicates processing of the last node in tree hashing -} - -// Initialization values. -var iv = [8]uint64{ - 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, - 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, 0x9b05688c2b3e6c1f, - 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, -} - -// Config is used to configure hash function parameters and keying. -// All parameters are optional. -type Config struct { - Size uint8 // digest size (if zero, default size of 64 bytes is used) - Key []byte // key for prefix-MAC - Salt []byte // salt (if < 16 bytes, padded with zeros) - Person []byte // personalization (if < 16 bytes, padded with zeros) - Tree *Tree // parameters for tree hashing -} - -// Tree represents parameters for tree hashing. -type Tree struct { - Fanout uint8 // fanout - MaxDepth uint8 // maximal depth - LeafSize uint32 // leaf maximal byte length (0 for unlimited) - NodeOffset uint64 // node offset (0 for first, leftmost or leaf) - NodeDepth uint8 // node depth (0 for leaves) - InnerHashSize uint8 // inner hash byte length - IsLastNode bool // indicates processing of the last node of layer -} - -var ( - defaultConfig = &Config{Size: Size} - config256 = &Config{Size: 32} -) - -func verifyConfig(c *Config) error { - if c.Size > Size { - return errors.New("digest size is too large") - } - if len(c.Key) > KeySize { - return errors.New("key is too large") - } - if len(c.Salt) > SaltSize { - // Smaller salt is okay: it will be padded with zeros. - return errors.New("salt is too large") - } - if len(c.Person) > PersonSize { - // Smaller personalization is okay: it will be padded with zeros. - return errors.New("personalization is too large") - } - if c.Tree != nil { - if c.Tree.Fanout == 1 { - return errors.New("fanout of 1 is not allowed in tree mode") - } - if c.Tree.MaxDepth < 2 { - return errors.New("incorrect tree depth") - } - if c.Tree.InnerHashSize < 1 || c.Tree.InnerHashSize > Size { - return errors.New("incorrect tree inner hash size") - } - } - return nil -} - -// New returns a new hash.Hash configured with the given Config. -// Config can be nil, in which case the default one is used, calculating 64-byte digest. -// Returns non-nil error if Config contains invalid parameters. -func New(c *Config) (hash.Hash, error) { - if c == nil { - c = defaultConfig - } else { - if c.Size == 0 { - // Set default size if it's zero. - c.Size = Size - } - if err := verifyConfig(c); err != nil { - return nil, err - } - } - d := new(digest) - d.initialize(c) - return d, nil -} - -// initialize initializes digest with the given -// config, which must be non-nil and verified. -func (d *digest) initialize(c *Config) { - // Create parameter block. - var p [BlockSize]byte - p[0] = c.Size - p[1] = uint8(len(c.Key)) - if c.Salt != nil { - copy(p[32:], c.Salt) - } - if c.Person != nil { - copy(p[48:], c.Person) - } - if c.Tree != nil { - p[2] = c.Tree.Fanout - p[3] = c.Tree.MaxDepth - binary.LittleEndian.PutUint32(p[4:], c.Tree.LeafSize) - binary.LittleEndian.PutUint64(p[8:], c.Tree.NodeOffset) - p[16] = c.Tree.NodeDepth - p[17] = c.Tree.InnerHashSize - } else { - p[2] = 1 - p[3] = 1 - } - - // Initialize. - d.size = c.Size - for i := 0; i < 8; i++ { - d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(p[i*8:]) - } - if c.Tree != nil && c.Tree.IsLastNode { - d.isLastNode = true - } - - // Process key. - if c.Key != nil { - copy(d.paddedKey[:], c.Key) - d.Write(d.paddedKey[:]) - d.isKeyed = true - } - // Save a copy of initialized state. - copy(d.ih[:], d.h[:]) -} - -// New512 returns a new hash.Hash computing the BLAKE2b 64-byte checksum. -func New512() hash.Hash { - d := new(digest) - d.initialize(defaultConfig) - return d -} - -// New256 returns a new hash.Hash computing the BLAKE2b 32-byte checksum. -func New256() hash.Hash { - d := new(digest) - d.initialize(config256) - return d -} - -// NewMAC returns a new hash.Hash computing BLAKE2b prefix- -// Message Authentication Code of the given size in bytes -// (up to 64) with the given key (up to 64 bytes in length). -func NewMAC(outBytes uint8, key []byte) hash.Hash { - d, err := New(&Config{Size: outBytes, Key: key}) - if err != nil { - panic(err.Error()) - } - return d -} - -// Reset resets the state of digest to the initial state -// after configuration and keying. -func (d *digest) Reset() { - copy(d.h[:], d.ih[:]) - d.t[0] = 0 - d.t[1] = 0 - d.f[0] = 0 - d.f[1] = 0 - d.nx = 0 - if d.isKeyed { - d.Write(d.paddedKey[:]) - } -} - -// Size returns the digest size in bytes. -func (d *digest) Size() int { return int(d.size) } - -// BlockSize returns the algorithm block size in bytes. -func (d *digest) BlockSize() int { return BlockSize } - -func (d *digest) Write(p []byte) (nn int, err error) { - nn = len(p) - left := BlockSize - d.nx - if len(p) > left { - // Process buffer. - copy(d.x[d.nx:], p[:left]) - p = p[left:] - compress(d, d.x[:]) - d.nx = 0 - } - // Process full blocks except for the last one. - if len(p) > BlockSize { - n := len(p) &^ (BlockSize - 1) - if n == len(p) { - n -= BlockSize - } - compress(d, p[:n]) - p = p[n:] - } - // Fill buffer. - d.nx += copy(d.x[d.nx:], p) - return -} - -// Sum returns the calculated checksum. -func (d *digest) Sum(in []byte) []byte { - // Make a copy of d so that caller can keep writing and summing. - d0 := *d - hash := d0.checkSum() - return append(in, hash[:d0.size]...) -} - -func (d *digest) checkSum() [Size]byte { - // Do not create unnecessary copies of the key. - if d.isKeyed { - for i := 0; i < len(d.paddedKey); i++ { - d.paddedKey[i] = 0 - } - } - - dec := BlockSize - uint64(d.nx) - if d.t[0] < dec { - d.t[1]-- - } - d.t[0] -= dec - - // Pad buffer with zeros. - for i := d.nx; i < len(d.x); i++ { - d.x[i] = 0 - } - // Set last block flag. - d.f[0] = 0xffffffffffffffff - if d.isLastNode { - d.f[1] = 0xffffffffffffffff - } - // Compress last block. - compress(d, d.x[:]) - - var out [Size]byte - j := 0 - for _, s := range d.h[:(d.size-1)/8+1] { - out[j+0] = byte(s >> 0) - out[j+1] = byte(s >> 8) - out[j+2] = byte(s >> 16) - out[j+3] = byte(s >> 24) - out[j+4] = byte(s >> 32) - out[j+5] = byte(s >> 40) - out[j+6] = byte(s >> 48) - out[j+7] = byte(s >> 56) - j += 8 - } - return out -} - -// Sum512 returns a 64-byte BLAKE2b hash of data. -func Sum512(data []byte) [64]byte { - var d digest - d.initialize(defaultConfig) - d.Write(data) - return d.checkSum() -} - -// Sum256 returns a 32-byte BLAKE2b hash of data. -func Sum256(data []byte) (out [32]byte) { - var d digest - d.initialize(config256) - d.Write(data) - sum := d.checkSum() - copy(out[:], sum[:32]) - return -} diff --git a/vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.go b/vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.go deleted file mode 100644 index ec53599f8..000000000 --- a/vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.go +++ /dev/null @@ -1,47 +0,0 @@ -//+build !noasm -//+build !appengine - -/* - * Minio Cloud Storage, (C) 2016 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 blake2b - -//go:noescape -func compressAVX2Loop(p []uint8, in, iv, t, f, shffle, out []uint64) - -func compressAVX2(d *digest, p []uint8) { - var ( - in [8]uint64 - out [8]uint64 - shffle [8]uint64 - ) - - // vector for PSHUFB instruction - shffle[0] = 0x0201000706050403 - shffle[1] = 0x0a09080f0e0d0c0b - shffle[2] = 0x0201000706050403 - shffle[3] = 0x0a09080f0e0d0c0b - shffle[4] = 0x0100070605040302 - shffle[5] = 0x09080f0e0d0c0b0a - shffle[6] = 0x0100070605040302 - shffle[7] = 0x09080f0e0d0c0b0a - - in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] = d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] - - compressAVX2Loop(p, in[:], iv[:], d.t[:], d.f[:], shffle[:], out[:]) - - d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] = out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7] -} diff --git a/vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.s b/vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.s deleted file mode 100644 index 24df234b5..000000000 --- a/vendor/github.com/minio/blake2b-simd/compressAvx2_amd64.s +++ /dev/null @@ -1,671 +0,0 @@ -//+build !noasm !appengine - -// -// Minio Cloud Storage, (C) 2016 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. -// - -// -// Based on AVX2 implementation from https://github.com/sneves/blake2-avx2/blob/master/blake2b-common.h -// -// Use github.com/fwessels/asm2plan9s on this file to assemble instructions to their Plan9 equivalent -// -// Assembly code below essentially follows the ROUND macro (see blake2b-round.h) which is defined as: -// #define ROUND(r) \ -// LOAD_MSG_ ##r ##_1(b0, b1); \ -// G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// LOAD_MSG_ ##r ##_2(b0, b1); \ -// G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ -// LOAD_MSG_ ##r ##_3(b0, b1); \ -// G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// LOAD_MSG_ ##r ##_4(b0, b1); \ -// G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); -// -// as well as the go equivalent in https://github.com/dchest/blake2b/blob/master/block.go -// -// As in the macro, G1/G2 in the 1st and 2nd half are identical (so literal copy of assembly) -// -// Rounds are also the same, except for the loading of the message (and rounds 1 & 11 and -// rounds 2 & 12 are identical) -// - -#define G1 \ - \ // G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); - BYTE $0xc5; BYTE $0xfd; BYTE $0xd4; BYTE $0xc4 \ // VPADDQ YMM0,YMM0,YMM4 /* v0 += m[0], v1 += m[2], v2 += m[4], v3 += m[6] */ - BYTE $0xc5; BYTE $0xfd; BYTE $0xd4; BYTE $0xc1 \ // VPADDQ YMM0,YMM0,YMM1 /* v0 += v4, v1 += v5, v2 += v6, v3 += v7 */ - BYTE $0xc5; BYTE $0xe5; BYTE $0xef; BYTE $0xd8 \ // VPXOR YMM3,YMM3,YMM0 /* v12 ^= v0, v13 ^= v1, v14 ^= v2, v15 ^= v3 */ - BYTE $0xc5; BYTE $0xfd; BYTE $0x70; BYTE $0xdb; BYTE $0xb1 \ // VPSHUFD YMM3,YMM3,0xb1 /* v12 = v12<<(64-32) | v12>>32, v13 = */ - BYTE $0xc5; BYTE $0xed; BYTE $0xd4; BYTE $0xd3 \ // VPADDQ YMM2,YMM2,YMM3 /* v8 += v12, v9 += v13, v10 += v14, v11 += v15 */ - BYTE $0xc5; BYTE $0xf5; BYTE $0xef; BYTE $0xca \ // VPXOR YMM1,YMM1,YMM2 /* v4 ^= v8, v5 ^= v9, v6 ^= v10, v7 ^= v11 */ - BYTE $0xc4; BYTE $0xe2; BYTE $0x75; BYTE $0x00; BYTE $0xce // VPSHUFB YMM1,YMM1,YMM6 /* v4 = v4<<(64-24) | v4>>24, ..., ..., v7 = v7<<(64-24) | v7>>24 */ - -#define G2 \ - BYTE $0xc5; BYTE $0xfd; BYTE $0xd4; BYTE $0xc5 \ // VPADDQ YMM0,YMM0,YMM5 /* v0 += m[1], v1 += m[3], v2 += m[5], v3 += m[7] */ - BYTE $0xc5; BYTE $0xfd; BYTE $0xd4; BYTE $0xc1 \ // VPADDQ YMM0,YMM0,YMM1 /* v0 += v4, v1 += v5, v2 += v6, v3 += v7 */ - BYTE $0xc5; BYTE $0xe5; BYTE $0xef; BYTE $0xd8 \ // VPXOR YMM3,YMM3,YMM0 /* v12 ^= v0, v13 ^= v1, v14 ^= v2, v15 ^= v3 */ - BYTE $0xc4; BYTE $0xe2; BYTE $0x65; BYTE $0x00; BYTE $0xdf \ // VPSHUFB YMM3,YMM3,YMM7 /* v12 = v12<<(64-16) | v12>>16, ..., ..., v15 = v15<<(64-16) | v15>>16 */ - BYTE $0xc5; BYTE $0xed; BYTE $0xd4; BYTE $0xd3 \ // VPADDQ YMM2,YMM2,YMM3 /* v8 += v12, v9 += v13, v10 += v14, v11 += v15 */ - BYTE $0xc5; BYTE $0xf5; BYTE $0xef; BYTE $0xca \ // VPXOR YMM1,YMM1,YMM2 /* v4 ^= v8, v5 ^= v9, v6 ^= v10, v7 ^= v11 */ - BYTE $0xc5; BYTE $0x75; BYTE $0xd4; BYTE $0xf9 \ // VPADDQ YMM15,YMM1,YMM1 /* temp reg = reg*2 */ - BYTE $0xc5; BYTE $0xf5; BYTE $0x73; BYTE $0xd1; BYTE $0x3f \ // VPSRLQ YMM1,YMM1,0x3f /* reg = reg>>63 */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x75; BYTE $0xef; BYTE $0xcf // VPXOR YMM1,YMM1,YMM15 /* ORed together: v4 = v4<<(64-63) | v4>>63, v5 = v5<<(64-63) | v5>>63 */ - -#define DIAGONALIZE \ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb \ // VPERMQ YMM3, YMM3, 0x93 - BYTE $0x93 \ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2 \ // VPERMQ YMM2, YMM2, 0x4e - BYTE $0x4e \ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 \ // VPERMQ YMM1, YMM1, 0x39 - BYTE $0x39 \ - // DO NOT DELETE -- macro delimiter (previous line extended) - -#define UNDIAGONALIZE \ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb \ // VPERMQ YMM3, YMM3, 0x39 - BYTE $0x39 \ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2 \ // VPERMQ YMM2, YMM2, 0x4e - BYTE $0x4e \ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 \ // VPERMQ YMM1, YMM1, 0x93 - BYTE $0x93 \ - // DO NOT DELETE -- macro delimiter (previous line extended) - -#define LOAD_SHUFFLE \ - MOVQ shffle+120(FP), SI \ // SI: &shuffle - BYTE $0xc5; BYTE $0xfe; BYTE $0x6f; BYTE $0x36 \ // VMOVDQU YMM6, [rsi] - BYTE $0xc5; BYTE $0xfe; BYTE $0x6f; BYTE $0x7e; BYTE $0x20 // VMOVDQU YMM7, 32[rsi] - -// func compressAVX2Loop(compressSSE(p []uint8, in, iv, t, f, shffle, out []uint64) -TEXT ·compressAVX2Loop(SB), 7, $0 - - // REGISTER USE - // Y0 - Y3: v0 - v15 - // Y4 - Y5: m[0] - m[7] - // Y6 - Y7: shuffle value - // Y8 - Y9: temp registers - // Y10 -Y13: copy of full message - // Y15: temp register - - // Load digest - MOVQ in+24(FP), SI // SI: &in - BYTE $0xc5; BYTE $0xfe; BYTE $0x6f; BYTE $0x06 // VMOVDQU YMM0, [rsi] - BYTE $0xc5; BYTE $0xfe; BYTE $0x6f; BYTE $0x4e; BYTE $0x20 // VMOVDQU YMM1, 32[rsi] - - // Already store digest into &out (so we can reload it later generically) - MOVQ out+144(FP), SI // SI: &out - BYTE $0xc5; BYTE $0xfe; BYTE $0x7f; BYTE $0x06 // VMOVDQU [rsi], YMM0 - BYTE $0xc5; BYTE $0xfe; BYTE $0x7f; BYTE $0x4e; BYTE $0x20 // VMOVDQU 32[rsi], YMM1 - - // Initialize message pointer and loop counter - MOVQ message+0(FP), DX // DX: &p (message) - MOVQ message_len+8(FP), R8 // R8: len(message) - SHRQ $7, R8 // len(message) / 128 - CMPQ R8, $0 - JEQ complete - -loop: - // Increment counter - MOVQ t+72(FP), SI // SI: &t - MOVQ 0(SI), R9 // - ADDQ $128, R9 // /* d.t[0] += BlockSize */ - MOVQ R9, 0(SI) // - CMPQ R9, $128 // /* if d.t[0] < BlockSize { */ - JGE noincr // - MOVQ 8(SI), R9 // - ADDQ $1, R9 // /* d.t[1]++ */ - MOVQ R9, 8(SI) // -noincr: // /* } */ - - // Load initialization vector - MOVQ iv+48(FP), SI // SI: &iv - BYTE $0xc5; BYTE $0xfe; BYTE $0x6f; BYTE $0x16 // VMOVDQU YMM2, [rsi] - BYTE $0xc5; BYTE $0xfe; BYTE $0x6f; BYTE $0x5e; BYTE $0x20 // VMOVDQU YMM3, 32[rsi] - MOVQ t+72(FP), SI // SI: &t - BYTE $0xc4; BYTE $0x63; BYTE $0x3d; BYTE $0x38; BYTE $0x06 // VINSERTI128 YMM8, YMM8, [rsi], 0 /* Y8 = t[0]+t[1] */ - BYTE $0x00 - MOVQ t+96(FP), SI // SI: &f - BYTE $0xc4; BYTE $0x63; BYTE $0x3d; BYTE $0x38; BYTE $0x06 // VINSERTI128 YMM8, YMM8, [rsi], 1 /* Y8 = t[0]+t[1]+f[0]+f[1] */ - BYTE $0x01 - BYTE $0xc4; BYTE $0xc1; BYTE $0x65; BYTE $0xef; BYTE $0xd8 // VPXOR YMM3,YMM3,YMM8 /* Y3 = Y3 ^ Y8 */ - - BYTE $0xc5; BYTE $0x7e; BYTE $0x6f; BYTE $0x12 // VMOVDQU YMM10, [rdx] /* Y10 = m[0]+ m[1]+ m[2]+ m[3] */ - BYTE $0xc5; BYTE $0x7e; BYTE $0x6f; BYTE $0x5a; BYTE $0x20 // VMOVDQU YMM11, 32[rdx] /* Y11 = m[4]+ m[5]+ m[6]+ m[7] */ - BYTE $0xc5; BYTE $0x7e; BYTE $0x6f; BYTE $0x62; BYTE $0x40 // VMOVDQU YMM12, 64[rdx] /* Y12 = m[8]+ m[9]+m[10]+m[11] */ - BYTE $0xc5; BYTE $0x7e; BYTE $0x6f; BYTE $0x6a; BYTE $0x60 // VMOVDQU YMM13, 96[rdx] /* Y13 = m[12]+m[13]+m[14]+m[15] */ - - LOAD_SHUFFLE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0xc1; BYTE $0x2d; BYTE $0x6c; BYTE $0xe3 // VPUNPCKLQDQ YMM4, YMM10, YMM11 /* m[0], m[4], m[2], m[6] */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x2d; BYTE $0x6d; BYTE $0xeb // VPUNPCKHQDQ YMM5, YMM10, YMM11 /* m[1], m[5], m[3], m[7] */ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xe4 // VPERMQ YMM4, YMM4, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xed // VPERMQ YMM5, YMM5, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0xc1; BYTE $0x1d; BYTE $0x6c; BYTE $0xe5 // VPUNPCKLQDQ YMM4, YMM12, YMM13 /* m[8], m[12], m[10], m[14] */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x1d; BYTE $0x6d; BYTE $0xed // VPUNPCKHQDQ YMM5, YMM12, YMM13 /* m[9], m[13], m[11], m[15] */ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xe4 // VPERMQ YMM4, YMM4, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xed // VPERMQ YMM5, YMM5, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 2 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc5 // VPUNPCKLQDQ YMM8, YMM11, YMM13 /* m[4], ____, ____, m[14] */ - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x03 /* m[14], m[4], ____, ____ */ /* xxxx 0011 = 0x03 */ - BYTE $0x03 - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xcd // VPUNPCKHQDQ YMM9, YMM12, YMM13 /* m[9], m[13], ____, ____ */ - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 /* m[9], m[13], ____, ____ */ /* 0010 0000 = 0x20 */ - BYTE $0x20 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc4 // VPERMQ YMM8, YMM12, 0x02 /* m[10], m[8], ____, ____ */ /* xxxx 0010 = 0x02 */ - BYTE $0x02 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0x30 /* ____, ____, m[15], ____ */ /* xx11 xxxx = 0x30 */ - BYTE $0x30 - BYTE $0xc4; BYTE $0x41; BYTE $0x35; BYTE $0x6c; BYTE $0xcb // VPUNPCKLQDQ YMM9, YMM9, YMM11 /* ____, ____, m[15], m[6] */ - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 /* m[9], m[13], m[15], m[6] */ /* 0011 0000 = 0x30 */ - BYTE $0x30 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc2 // VPERMQ YMM8, YMM10, 0x01 /* m[1], m[0], ____, ____ */ /* xxxx 0001 = 0x01 */ - BYTE $0x01 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xcc // VPUNPCKHQDQ YMM9, YMM11, YMM12 /* m[5], ____, ____, m[11] */ - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x03 /* m[11], m[5], ____, ____ */ /* xxxx 0011 = 0x03 */ - BYTE $0x03 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 /* m[1], m[0], m[11], m[5] */ /* 0010 0000 = 0x20 */ - BYTE $0x20 - - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc5 // VPUNPCKLQDQ YMM8, YMM10, YMM13 /* ___, m[12], m[2], ____ */ - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x09 /* m[12], m[2], ____, ____ */ /* xxxx 1001 = 0x09 */ - BYTE $0x09 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xca // VPUNPCKHQDQ YMM9, YMM11, YMM10 /* ____, ____, m[7], m[3] */ - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 /* m[9], m[13], m[15], m[6] */ /* 0011 0000 = 0x30 */ - BYTE $0x30 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 3 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc5 // VPERMQ YMM8, YMM13, 0x00 - BYTE $0x00 - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xc0 // VPUNPCKHQDQ YMM8, YMM12, YMM8 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xcd // VPUNPCKHQDQ YMM9, YMM11, YMM13 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x21 - BYTE $0x21 - - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6c; BYTE $0xc2 // VPUNPCKLQDQ YMM8, YMM12, YMM10 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0x55 - BYTE $0x55 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM10, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 - BYTE $0x30 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc2 // VPERMQ YMM8, YMM10, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6c; BYTE $0xc0 // VPUNPCKLQDQ YMM8, YMM12, YMM8 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xcc // VPUNPCKHQDQ YMM9, YMM11, YMM12 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x31 - BYTE $0x31 - - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xc3 // VPUNPCKLQDQ YMM8, YMM13, YMM11 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcb // VPERMQ YMM9, YMM11, 0x00 - BYTE $0x00 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6d; BYTE $0xc9 // VPUNPCKHQDQ YMM9, YMM10, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x21 - BYTE $0x21 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 4 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xc2 // VPUNPCKHQDQ YMM8, YMM11, YMM10 - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xcc // VPUNPCKHQDQ YMM9, YMM13, YMM12 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x21 - BYTE $0x21 - - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xc2 // VPUNPCKHQDQ YMM8, YMM12, YMM10 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0x08 - BYTE $0x08 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x20 - BYTE $0x20 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc3 // VPERMQ YMM8, YMM11, 0x55 - BYTE $0x55 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc0 // VPUNPCKLQDQ YMM8, YMM10, YMM8 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM11, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x21 - BYTE $0x21 - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc4 // VPUNPCKLQDQ YMM8, YMM11, YMM12 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xcc // VPUNPCKLQDQ YMM9, YMM10, YMM12 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x21 - BYTE $0x21 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 5 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xc3 // VPUNPCKHQDQ YMM8, YMM12, YMM11 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xcc // VPUNPCKLQDQ YMM9, YMM10, YMM12 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x30 - BYTE $0x30 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc3 // VPERMQ YMM8, YMM11, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc0 // VPUNPCKLQDQ YMM8, YMM10, YMM8 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM11, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x20 - BYTE $0x20 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc4 // VPERMQ YMM8, YMM12, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xc0 // VPUNPCKLQDQ YMM8, YMM13, YMM8 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xca // VPERMQ YMM9, YMM10, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM11, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x31 - BYTE $0x31 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc5 // VPERMQ YMM8, YMM13, 0x00 - BYTE $0x00 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6d; BYTE $0xc0 // VPUNPCKHQDQ YMM8, YMM10, YMM8 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0x55 - BYTE $0x55 - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM12, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x20 - BYTE $0x20 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 6 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc3 // VPUNPCKLQDQ YMM8, YMM10, YMM11 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xcc // VPUNPCKLQDQ YMM9, YMM10, YMM12 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x21 - BYTE $0x21 - - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xc4 // VPUNPCKLQDQ YMM8, YMM13, YMM12 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xca // VPUNPCKHQDQ YMM9, YMM12, YMM10 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 - BYTE $0x30 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc3 // VPERMQ YMM8, YMM11, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xca // VPUNPCKHQDQ YMM9, YMM13, YMM10 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x30 - BYTE $0x30 - - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xc3 // VPUNPCKHQDQ YMM8, YMM13, YMM11 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcc // VPERMQ YMM9, YMM12, 0x55 - BYTE $0x55 - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM13, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 - BYTE $0x30 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 7 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc2 // VPERMQ YMM8, YMM10, 0x55 - BYTE $0x55 - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xc0 // VPUNPCKLQDQ YMM8, YMM13, YMM8 - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xcb // VPUNPCKLQDQ YMM9, YMM13, YMM11 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x30 - BYTE $0x30 - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xc5 // VPUNPCKHQDQ YMM8, YMM11, YMM13 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcc // VPERMQ YMM9, YMM12, 0xaa - BYTE $0xaa - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xc9 // VPUNPCKHQDQ YMM9, YMM13, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x20 - BYTE $0x20 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc3 // VPUNPCKLQDQ YMM8, YMM10, YMM11 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcc // VPERMQ YMM9, YMM12, 0x01 - BYTE $0x01 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 - BYTE $0x20 - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xc2 // VPUNPCKHQDQ YMM8, YMM11, YMM10 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcc // VPERMQ YMM9, YMM12, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM10, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x31 - BYTE $0x31 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 8 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xc3 // VPUNPCKHQDQ YMM8, YMM13, YMM11 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xca // VPERMQ YMM9, YMM10, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xc9 // VPUNPCKLQDQ YMM9, YMM13, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 - BYTE $0x20 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc5 // VPERMQ YMM8, YMM13, 0xaa - BYTE $0xaa - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xc0 // VPUNPCKHQDQ YMM8, YMM12, YMM8 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6d; BYTE $0xcc // VPUNPCKHQDQ YMM9, YMM10, YMM12 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x21 - BYTE $0x21 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xc5 // VPUNPCKHQDQ YMM8, YMM11, YMM13 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6c; BYTE $0xca // VPUNPCKLQDQ YMM9, YMM12, YMM10 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x0c - BYTE $0x0c - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 - BYTE $0x20 - - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc3 // VPUNPCKLQDQ YMM8, YMM10, YMM11 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xcc // VPUNPCKLQDQ YMM9, YMM11, YMM12 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 - BYTE $0x30 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 9 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc5 // VPUNPCKLQDQ YMM8, YMM11, YMM13 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xca // VPERMQ YMM9, YMM10, 0x00 - BYTE $0x00 - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xc9 // VPUNPCKHQDQ YMM9, YMM12, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x31 - BYTE $0x31 - - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xc4 // VPUNPCKHQDQ YMM8, YMM13, YMM12 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcc // VPERMQ YMM9, YMM12, 0x00 - BYTE $0x00 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6d; BYTE $0xc9 // VPUNPCKHQDQ YMM9, YMM10, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x31 - BYTE $0x31 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcc // VPERMQ YMM9, YMM12, 0xaa - BYTE $0xaa - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6d; BYTE $0xc9 // VPUNPCKHQDQ YMM9, YMM10, YMM9 - BYTE $0xc4; BYTE $0xc3; BYTE $0x15; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM13, YMM9, 0x20 - BYTE $0x20 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc3 // VPERMQ YMM8, YMM11, 0xff - BYTE $0xff - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc0 // VPUNPCKLQDQ YMM8, YMM10, YMM8 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcb // VPERMQ YMM9, YMM11, 0x04 - BYTE $0x04 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x21 - BYTE $0x21 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 10 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc4 // VPERMQ YMM8, YMM12, 0x20 - BYTE $0x20 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xca // VPUNPCKHQDQ YMM9, YMM11, YMM10 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x31 - BYTE $0x31 - - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc3 // VPUNPCKLQDQ YMM8, YMM10, YMM11 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcb // VPERMQ YMM9, YMM11, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x31 - BYTE $0x31 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6d; BYTE $0xc4 // VPUNPCKHQDQ YMM8, YMM13, YMM12 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6d; BYTE $0xcd // VPUNPCKHQDQ YMM9, YMM10, YMM13 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x60 - BYTE $0x60 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x31 - BYTE $0x31 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc5 // VPERMQ YMM8, YMM13, 0xaa - BYTE $0xaa - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xc0 // VPUNPCKHQDQ YMM8, YMM12, YMM8 - BYTE $0xc4; BYTE $0x41; BYTE $0x15; BYTE $0x6c; BYTE $0xca // VPUNPCKLQDQ YMM9, YMM13, YMM10 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x21 - BYTE $0x21 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 1 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0xc1; BYTE $0x2d; BYTE $0x6c; BYTE $0xe3 // VPUNPCKLQDQ YMM4, YMM10, YMM11 /* m[0], m[4], m[2], m[6] */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x2d; BYTE $0x6d; BYTE $0xeb // VPUNPCKHQDQ YMM5, YMM10, YMM11 /* m[1], m[5], m[3], m[7] */ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xe4 // VPERMQ YMM4, YMM4, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xed // VPERMQ YMM5, YMM5, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0xc1; BYTE $0x1d; BYTE $0x6c; BYTE $0xe5 // VPUNPCKLQDQ YMM4, YMM12, YMM13 /* m[8], m[12], m[10], m[14] */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x1d; BYTE $0x6d; BYTE $0xed // VPUNPCKHQDQ YMM5, YMM12, YMM13 /* m[9], m[13], m[11], m[15] */ - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xe4 // VPERMQ YMM4, YMM4, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xed // VPERMQ YMM5, YMM5, 0xd8 /* 0x1101 1000 = 0xd8 */ - BYTE $0xd8 - - G1 - G2 - - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 2 - /////////////////////////////////////////////////////////////////////////// - - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6c; BYTE $0xc5 // VPUNPCKLQDQ YMM8, YMM11, YMM13 /* m[4], ____, ____, m[14] */ - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x03 /* m[14], m[4], ____, ____ */ /* xxxx 0011 = 0x03 */ - BYTE $0x03 - BYTE $0xc4; BYTE $0x41; BYTE $0x1d; BYTE $0x6d; BYTE $0xcd // VPUNPCKHQDQ YMM9, YMM12, YMM13 /* m[9], m[13], ____, ____ */ - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 /* m[9], m[13], ____, ____ */ /* 0010 0000 = 0x20 */ - BYTE $0x20 - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc4 // VPERMQ YMM8, YMM12, 0x02 /* m[10], m[8], ____, ____ */ /* xxxx 0010 = 0x02 */ - BYTE $0x02 - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xcd // VPERMQ YMM9, YMM13, 0x30 /* ____, ____, m[15], ____ */ /* xx11 xxxx = 0x30 */ - BYTE $0x30 - BYTE $0xc4; BYTE $0x41; BYTE $0x35; BYTE $0x6c; BYTE $0xcb // VPUNPCKLQDQ YMM9, YMM9, YMM11 /* ____, ____, m[15], m[6] */ - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 /* m[9], m[13], m[15], m[6] */ /* 0011 0000 = 0x30 */ - BYTE $0x30 - - G1 - G2 - - DIAGONALIZE - - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc2 // VPERMQ YMM8, YMM10, 0x01 /* m[1], m[0], ____, ____ */ /* xxxx 0001 = 0x01 */ - BYTE $0x01 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xcc // VPUNPCKHQDQ YMM9, YMM11, YMM12 /* m[5], ____, ____, m[11] */ - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc9 // VPERMQ YMM9, YMM9, 0x03 /* m[11], m[5], ____, ____ */ /* xxxx 0011 = 0x03 */ - BYTE $0x03 - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe1 // VPERM2I128 YMM4, YMM8, YMM9, 0x20 /* m[1], m[0], m[11], m[5] */ /* 0010 0000 = 0x20 */ - BYTE $0x20 - - BYTE $0xc4; BYTE $0x41; BYTE $0x2d; BYTE $0x6c; BYTE $0xc5 // VPUNPCKLQDQ YMM8, YMM10, YMM13 /* ___, m[12], m[2], ____ */ - BYTE $0xc4; BYTE $0x43; BYTE $0xfd; BYTE $0x00; BYTE $0xc0 // VPERMQ YMM8, YMM8, 0x09 /* m[12], m[2], ____, ____ */ /* xxxx 1001 = 0x09 */ - BYTE $0x09 - BYTE $0xc4; BYTE $0x41; BYTE $0x25; BYTE $0x6d; BYTE $0xca // VPUNPCKHQDQ YMM9, YMM11, YMM10 /* ____, ____, m[7], m[3] */ - BYTE $0xc4; BYTE $0xc3; BYTE $0x3d; BYTE $0x46; BYTE $0xe9 // VPERM2I128 YMM5, YMM8, YMM9, 0x30 /* m[9], m[13], m[15], m[6] */ /* 0011 0000 = 0x30 */ - BYTE $0x30 - - G1 - G2 - - UNDIAGONALIZE - - // Reload digest (most current value store in &out) - MOVQ out+144(FP), SI // SI: &in - BYTE $0xc5; BYTE $0x7e; BYTE $0x6f; BYTE $0x26 // VMOVDQU YMM12, [rsi] - BYTE $0xc5; BYTE $0x7e; BYTE $0x6f; BYTE $0x6e; BYTE $0x20 // VMOVDQU YMM13, 32[rsi] - - BYTE $0xc5; BYTE $0xfd; BYTE $0xef; BYTE $0xc2 // VPXOR YMM0,YMM0,YMM2 /* X0 = X0 ^ X4, X1 = X1 ^ X5 */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x7d; BYTE $0xef; BYTE $0xc4 // VPXOR YMM0,YMM0,YMM12 /* X0 = X0 ^ X12, X1 = X1 ^ X13 */ - BYTE $0xc5; BYTE $0xf5; BYTE $0xef; BYTE $0xcb // VPXOR YMM1,YMM1,YMM3 /* X2 = X2 ^ X6, X3 = X3 ^ X7 */ - BYTE $0xc4; BYTE $0xc1; BYTE $0x75; BYTE $0xef; BYTE $0xcd // VPXOR YMM1,YMM1,YMM13 /* X2 = X2 ^ X14, X3 = X3 ^ X15 */ - - // Store digest into &out - MOVQ out+144(FP), SI // SI: &out - BYTE $0xc5; BYTE $0xfe; BYTE $0x7f; BYTE $0x06 // VMOVDQU [rsi], YMM0 - BYTE $0xc5; BYTE $0xfe; BYTE $0x7f; BYTE $0x4e; BYTE $0x20 // VMOVDQU 32[rsi], YMM1 - - // Increment message pointer and check if there's more to do - ADDQ $128, DX // message += 128 - SUBQ $1, R8 - JNZ loop - -complete: - BYTE $0xc5; BYTE $0xf8; BYTE $0x77 // VZEROUPPER /* Prevent further context switches */ - RET - diff --git a/vendor/github.com/minio/blake2b-simd/compressAvx_amd64.go b/vendor/github.com/minio/blake2b-simd/compressAvx_amd64.go deleted file mode 100644 index cfa12c04f..000000000 --- a/vendor/github.com/minio/blake2b-simd/compressAvx_amd64.go +++ /dev/null @@ -1,41 +0,0 @@ -//+build !noasm -//+build !appengine - -/* - * Minio Cloud Storage, (C) 2016 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 blake2b - -//go:noescape -func blockAVXLoop(p []uint8, in, iv, t, f, shffle, out []uint64) - -func compressAVX(d *digest, p []uint8) { - var ( - in [8]uint64 - out [8]uint64 - shffle [2]uint64 - ) - - // vector for PSHUFB instruction - shffle[0] = 0x0201000706050403 - shffle[1] = 0x0a09080f0e0d0c0b - - in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] = d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] - - blockAVXLoop(p, in[:], iv[:], d.t[:], d.f[:], shffle[:], out[:]) - - d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] = out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7] -} diff --git a/vendor/github.com/minio/blake2b-simd/compressAvx_amd64.s b/vendor/github.com/minio/blake2b-simd/compressAvx_amd64.s deleted file mode 100644 index f68e17392..000000000 --- a/vendor/github.com/minio/blake2b-simd/compressAvx_amd64.s +++ /dev/null @@ -1,682 +0,0 @@ -//+build !noasm !appengine - -// -// Minio Cloud Storage, (C) 2016 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. -// - -// -// Based on SSE implementation from https://github.com/BLAKE2/BLAKE2/blob/master/sse/blake2b.c -// -// Use github.com/fwessels/asm2plan9s on this file to assemble instructions to their Plan9 equivalent -// -// Assembly code below essentially follows the ROUND macro (see blake2b-round.h) which is defined as: -// #define ROUND(r) \ -// LOAD_MSG_ ##r ##_1(b0, b1); \ -// G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// LOAD_MSG_ ##r ##_2(b0, b1); \ -// G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ -// LOAD_MSG_ ##r ##_3(b0, b1); \ -// G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// LOAD_MSG_ ##r ##_4(b0, b1); \ -// G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); -// -// as well as the go equivalent in https://github.com/dchest/blake2b/blob/master/block.go -// -// As in the macro, G1/G2 in the 1st and 2nd half are identical (so literal copy of assembly) -// -// Rounds are also the same, except for the loading of the message (and rounds 1 & 11 and -// rounds 2 & 12 are identical) -// - -#define G1 \ - \ // G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); - LONG $0xd479c1c4; BYTE $0xc0 \ // VPADDQ XMM0,XMM0,XMM8 /* v0 += m[0], v1 += m[2] */ - LONG $0xd471c1c4; BYTE $0xc9 \ // VPADDQ XMM1,XMM1,XMM9 /* v2 += m[4], v3 += m[6] */ - LONG $0xc2d4f9c5 \ // VPADDQ XMM0,XMM0,XMM2 /* v0 += v4, v1 += v5 */ - LONG $0xcbd4f1c5 \ // VPADDQ XMM1,XMM1,XMM3 /* v2 += v6, v3 += v7 */ - LONG $0xf0efc9c5 \ // VPXOR XMM6,XMM6,XMM0 /* v12 ^= v0, v13 ^= v1 */ - LONG $0xf9efc1c5 \ // VPXOR XMM7,XMM7,XMM1 /* v14 ^= v2, v15 ^= v3 */ - LONG $0xf670f9c5; BYTE $0xb1 \ // VPSHUFD XMM6,XMM6,0xb1 /* v12 = v12<<(64-32) | v12>>32, v13 = v13<<(64-32) | v13>>32 */ - LONG $0xff70f9c5; BYTE $0xb1 \ // VPSHUFD XMM7,XMM7,0xb1 /* v14 = v14<<(64-32) | v14>>32, v15 = v15<<(64-32) | v15>>32 */ - LONG $0xe6d4d9c5 \ // VPADDQ XMM4,XMM4,XMM6 /* v8 += v12, v9 += v13 */ - LONG $0xefd4d1c5 \ // VPADDQ XMM5,XMM5,XMM7 /* v10 += v14, v11 += v15 */ - LONG $0xd4efe9c5 \ // VPXOR XMM2,XMM2,XMM4 /* v4 ^= v8, v5 ^= v9 */ - LONG $0xddefe1c5 \ // VPXOR XMM3,XMM3,XMM5 /* v6 ^= v10, v7 ^= v11 */ - LONG $0x0069c2c4; BYTE $0xd4 \ // VPSHUFB XMM2,XMM2,XMM12 /* v4 = v4<<(64-24) | v4>>24, v5 = v5<<(64-24) | v5>>24 */ - LONG $0x0061c2c4; BYTE $0xdc // VPSHUFB XMM3,XMM3,XMM12 /* v6 = v6<<(64-24) | v6>>24, v7 = v7<<(64-24) | v7>>24 */ - -#define G2 \ - \ // G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); - LONG $0xd479c1c4; BYTE $0xc2 \ // VPADDQ XMM0,XMM0,XMM10 /* v0 += m[1], v1 += m[3] */ - LONG $0xd471c1c4; BYTE $0xcb \ // VPADDQ XMM1,XMM1,XMM11 /* v2 += m[5], v3 += m[7] */ - LONG $0xc2d4f9c5 \ // VPADDQ XMM0,XMM0,XMM2 /* v0 += v4, v1 += v5 */ - LONG $0xcbd4f1c5 \ // VPADDQ XMM1,XMM1,XMM3 /* v2 += v6, v3 += v7 */ - LONG $0xf0efc9c5 \ // VPXOR XMM6,XMM6,XMM0 /* v12 ^= v0, v13 ^= v1 */ - LONG $0xf9efc1c5 \ // VPXOR XMM7,XMM7,XMM1 /* v14 ^= v2, v15 ^= v3 */ - LONG $0xf670fbc5; BYTE $0x39 \ // VPSHUFLW XMM6,XMM6,0x39 /* combined with next ... */ - LONG $0xf670fac5; BYTE $0x39 \ // VPSHUFHW XMM6,XMM6,0x39 /* v12 = v12<<(64-16) | v12>>16, v13 = v13<<(64-16) | v13>>16 */ - LONG $0xff70fbc5; BYTE $0x39 \ // VPSHUFLW XMM7,XMM7,0x39 /* combined with next ... */ - LONG $0xff70fac5; BYTE $0x39 \ // VPSHUFHW XMM7,XMM7,0x39 /* v14 = v14<<(64-16) | v14>>16, v15 = v15<<(64-16) | v15>>16 */ - LONG $0xe6d4d9c5 \ // VPADDQ XMM4,XMM4,XMM6 /* v8 += v12, v9 += v13 */ - LONG $0xefd4d1c5 \ // VPADDQ XMM5,XMM5,XMM7 /* v10 += v14, v11 += v15 */ - LONG $0xd4efe9c5 \ // VPXOR XMM2,XMM2,XMM4 /* v4 ^= v8, v5 ^= v9 */ - LONG $0xddefe1c5 \ // VPXOR XMM3,XMM3,XMM5 /* v6 ^= v10, v7 ^= v11 */ - LONG $0xfad469c5 \ // VPADDQ XMM15,XMM2,XMM2 /* temp reg = reg*2 */ - LONG $0xd273e9c5; BYTE $0x3f \ // VPSRLQ XMM2,XMM2,0x3f /* reg = reg>>63 */ - LONG $0xef69c1c4; BYTE $0xd7 \ // VPXOR XMM2,XMM2,XMM15 /* ORed together: v4 = v4<<(64-63) | v4>>63, v5 = v5<<(64-63) | v5>>63 */ - LONG $0xfbd461c5 \ // VPADDQ XMM15,XMM3,XMM3 /* temp reg = reg*2 */ - LONG $0xd373e1c5; BYTE $0x3f \ // VPSRLQ XMM3,XMM3,0x3f /* reg = reg>>63 */ - LONG $0xef61c1c4; BYTE $0xdf // VPXOR XMM3,XMM3,XMM15 /* ORed together: v6 = v6<<(64-63) | v6>>63, v7 = v7<<(64-63) | v7>>63 */ - -#define DIAGONALIZE \ - \ // DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); - MOVOU X6, X13 \ /* t0 = row4l;\ */ - MOVOU X2, X14 \ /* t1 = row2l;\ */ - MOVOU X4, X6 \ /* row4l = row3l;\ */ - MOVOU X5, X4 \ /* row3l = row3h;\ */ - MOVOU X6, X5 \ /* row3h = row4l;\ */ - LONG $0x6c1141c4; BYTE $0xfd \ // VPUNPCKLQDQ XMM15, XMM13, XMM13 /* _mm_unpacklo_epi64(t0, t0) */ - LONG $0x6d41c1c4; BYTE $0xf7 \ // VPUNPCKHQDQ XMM6, XMM7, XMM15 /* row4l = _mm_unpackhi_epi64(row4h, ); \ */ - LONG $0xff6c41c5 \ // VPUNPCKLQDQ XMM15, XMM7, XMM7 /* _mm_unpacklo_epi64(row4h, row4h) */ - LONG $0x6d11c1c4; BYTE $0xff \ // VPUNPCKHQDQ XMM7, XMM13, XMM15 /* row4h = _mm_unpackhi_epi64(t0, ); \ */ - LONG $0xfb6c61c5 \ // VPUNPCKLQDQ XMM15, XMM3, XMM3 /* _mm_unpacklo_epi64(row2h, row2h) */ - LONG $0x6d69c1c4; BYTE $0xd7 \ // VPUNPCKHQDQ XMM2, XMM2, XMM15 /* row2l = _mm_unpackhi_epi64(row2l, ); \ */ - LONG $0x6c0941c4; BYTE $0xfe \ // VPUNPCKLQDQ XMM15, XMM14, XMM14 /* _mm_unpacklo_epi64(t1, t1) */ - LONG $0x6d61c1c4; BYTE $0xdf // VPUNPCKHQDQ XMM3, XMM3, XMM15 /* row2h = _mm_unpackhi_epi64(row2h, ) */ - -#define UNDIAGONALIZE \ - \ // UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); - MOVOU X4, X13 \ /* t0 = row3l;\ */ - MOVOU X5, X4 \ /* row3l = row3h;\ */ - MOVOU X13, X5 \ /* row3h = t0;\ */ - MOVOU X2, X13 \ /* t0 = row2l;\ */ - MOVOU X6, X14 \ /* t1 = row4l;\ */ - LONG $0xfa6c69c5 \ // VPUNPCKLQDQ XMM15, XMM2, XMM2 /* _mm_unpacklo_epi64(row2l, row2l) */ - LONG $0x6d61c1c4; BYTE $0xd7 \ // VPUNPCKHQDQ XMM2, XMM3, XMM15 /* row2l = _mm_unpackhi_epi64(row2h, ); \ */ - LONG $0xfb6c61c5 \ // VPUNPCKLQDQ XMM15, XMM3, XMM3 /* _mm_unpacklo_epi64(row2h, row2h) */ - LONG $0x6d11c1c4; BYTE $0xdf \ // VPUNPCKHQDQ XMM3, XMM13, XMM15 /* row2h = _mm_unpackhi_epi64(t0, ); \ */ - LONG $0xff6c41c5 \ // VPUNPCKLQDQ XMM15, XMM7, XMM7 /* _mm_unpacklo_epi64(row4h, row4h) */ - LONG $0x6d49c1c4; BYTE $0xf7 \ // VPUNPCKHQDQ XMM6, XMM6, XMM15 /* row4l = _mm_unpackhi_epi64(row4l, ); \ */ - LONG $0x6c0941c4; BYTE $0xfe \ // VPUNPCKLQDQ XMM15, XMM14, XMM14 /* _mm_unpacklo_epi64(t1, t1) */ - LONG $0x6d41c1c4; BYTE $0xff // VPUNPCKHQDQ XMM7, XMM7, XMM15 /* row4h = _mm_unpackhi_epi64(row4h, ) */ - -#define LOAD_SHUFFLE \ - \ // Load shuffle value - MOVQ shffle+120(FP), SI \ // SI: &shuffle - MOVOU 0(SI), X12 // X12 = 03040506 07000102 0b0c0d0e 0f08090a - -// func blockAVXLoop(p []uint8, in, iv, t, f, shffle, out []uint64) -TEXT ·blockAVXLoop(SB), 7, $0 - // REGISTER USE - // R8: loop counter - // DX: message pointer - // SI: temp pointer for loading - // X0 - X7: v0 - v15 - // X8 - X11: m[0] - m[7] - // X12: shuffle value - // X13 - X15: temp registers - - // Load digest - MOVQ in+24(FP), SI // SI: &in - MOVOU 0(SI), X0 // X0 = in[0]+in[1] /* row1l = LOAD( &S->h[0] ); */ - MOVOU 16(SI), X1 // X1 = in[2]+in[3] /* row1h = LOAD( &S->h[2] ); */ - MOVOU 32(SI), X2 // X2 = in[4]+in[5] /* row2l = LOAD( &S->h[4] ); */ - MOVOU 48(SI), X3 // X3 = in[6]+in[7] /* row2h = LOAD( &S->h[6] ); */ - - // Already store digest into &out (so we can reload it later generically) - MOVQ out+144(FP), SI // SI: &out - MOVOU X0, 0(SI) // out[0]+out[1] = X0 - MOVOU X1, 16(SI) // out[2]+out[3] = X1 - MOVOU X2, 32(SI) // out[4]+out[5] = X2 - MOVOU X3, 48(SI) // out[6]+out[7] = X3 - - // Initialize message pointer and loop counter - MOVQ message+0(FP), DX // DX: &p (message) - MOVQ message_len+8(FP), R8 // R8: len(message) - SHRQ $7, R8 // len(message) / 128 - CMPQ R8, $0 - JEQ complete - -loop: - // Increment counter - MOVQ t+72(FP), SI // SI: &t - MOVQ 0(SI), R9 - ADDQ $128, R9 // /* d.t[0] += BlockSize */ - MOVQ R9, 0(SI) - CMPQ R9, $128 // /* if d.t[0] < BlockSize { */ - JGE noincr - MOVQ 8(SI), R9 - ADDQ $1, R9 // /* d.t[1]++ */ - MOVQ R9, 8(SI) -noincr: // /* } */ - - // Load initialization vector - MOVQ iv+48(FP), SI // SI: &iv - MOVOU 0(SI), X4 // X4 = iv[0]+iv[1] /* row3l = LOAD( &blake2b_IV[0] ); */ - MOVOU 16(SI), X5 // X5 = iv[2]+iv[3] /* row3h = LOAD( &blake2b_IV[2] ); */ - MOVOU 32(SI), X6 // X6 = iv[4]+iv[5] /* LOAD( &blake2b_IV[4] ) */ - MOVOU 48(SI), X7 // X7 = iv[6]+iv[7] /* LOAD( &blake2b_IV[6] ) */ - MOVQ t+72(FP), SI // SI: &t - MOVOU 0(SI), X8 // X8 = t[0]+t[1] /* LOAD( &S->t[0] ) */ - PXOR X8, X6 // X6 = X6 ^ X8 /* row4l = _mm_xor_si128( , ); */ - MOVQ t+96(FP), SI // SI: &f - MOVOU 0(SI), X8 // X8 = f[0]+f[1] /* LOAD( &S->f[0] ) */ - PXOR X8, X7 // X7 = X7 ^ X8 /* row4h = _mm_xor_si128( , ); */ - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+m[1] - MOVOU 16(DX), X13 // X13 = m[2]+m[3] - MOVOU 32(DX), X14 // X14 = m[4]+m[5] - MOVOU 48(DX), X15 // X15 = m[6]+m[7] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[0], m[2] */ - LONG $0x6c0941c4; BYTE $0xcf // VPUNPCKLQDQ XMM9, XMM14, XMM15 /* m[4], m[6] */ - LONG $0x6d1941c4; BYTE $0xd5 // VPUNPCKHQDQ XMM10, XMM12, XMM13 /* m[1], m[3] */ - LONG $0x6d0941c4; BYTE $0xdf // VPUNPCKHQDQ XMM11, XMM14, XMM15 /* m[5], m[7] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 64(DX), X12 // X12 = m[8]+ m[9] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[8],m[10] */ - LONG $0x6c0941c4; BYTE $0xcf // VPUNPCKLQDQ XMM9, XMM14, XMM15 /* m[12],m[14] */ - LONG $0x6d1941c4; BYTE $0xd5 // VPUNPCKHQDQ XMM10, XMM12, XMM13 /* m[9],m[11] */ - LONG $0x6d0941c4; BYTE $0xdf // VPUNPCKHQDQ XMM11, XMM14, XMM15 /* m[13],m[15] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 2 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 112(DX), X12 // X12 = m[14]+m[15] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[14], m[4] */ - LONG $0x6d0941c4; BYTE $0xcf // VPUNPCKHQDQ XMM9, XMM14, XMM15 /* m[9], m[13] */ - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 48(DX), X15 // X15 = m[6]+ m[7] - LONG $0x6c1141c4; BYTE $0xd6 // VPUNPCKLQDQ XMM10, XMM13, XMM14 /* m[10], m[8] */ - LONG $0x0f0143c4; WORD $0x08dc // VPALIGNR XMM11, XMM15, XMM12, 0x8 /* m[15], m[6] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - LONG $0x0f1943c4; WORD $0x08c4 // VPALIGNR XMM8, XMM12, XMM12, 0x8 /* m[1], m[0] */ - LONG $0x6d0941c4; BYTE $0xcd // VPUNPCKHQDQ XMM9, XMM14, XMM13 /* m[11], m[5] */ - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - LONG $0x6c0941c4; BYTE $0xd4 // VPUNPCKLQDQ XMM10, XMM14, XMM12 /* m[12], m[2] */ - LONG $0x6d1141c4; BYTE $0xdc // VPUNPCKHQDQ XMM11, XMM13, XMM12 /* m[7], m[3] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 3 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 32(DX), X12 // X12 = m[4]+ m[5] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x0f0943c4; WORD $0x08c5 // VPALIGNR XMM8, XMM14, XMM13, 0x8 /* m[11], m[12] */ - LONG $0x6d1941c4; BYTE $0xcf // VPUNPCKHQDQ XMM9, XMM12, XMM15 /* m[5], m[15] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 64(DX), X15 // X15 = m[8]+ m[9] - LONG $0x6c0141c4; BYTE $0xd4 // VPUNPCKLQDQ XMM10, XMM15, XMM12 /* m[8], m[0] */ - LONG $0x6d0941c4; BYTE $0xde // VPUNPCKHQDQ XMM11, XMM14, XMM14 /* ___, m[13] */ - LONG $0x6c1141c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM13, XMM11 /* m[2], ___ */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - LONG $0x6d1941c4; BYTE $0xc4 // VPUNPCKHQDQ XMM8, XMM12, XMM12 /* ___, m[3] */ - LONG $0x6c0141c4; BYTE $0xc0 // VPUNPCKLQDQ XMM8, XMM15, XMM8 /* m[10], ___ */ - LONG $0x6d1141c4; BYTE $0xce // VPUNPCKHQDQ XMM9, XMM13, XMM14 /* m[7], m[9] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X14 // X14 = m[4]+ m[5] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6c0141c4; BYTE $0xd5 // VPUNPCKLQDQ XMM10, XMM15, XMM13 /* m[14], m[6] */ - LONG $0x0f0943c4; WORD $0x08dc // VPALIGNR XMM11, XMM14, XMM12, 0x8 /* m[1], m[4] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 4 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - LONG $0x6d1141c4; BYTE $0xc4 // VPUNPCKHQDQ XMM8, XMM13, XMM12 /* m[7], m[3] */ - LONG $0x6d0141c4; BYTE $0xce // VPUNPCKHQDQ XMM9, XMM15, XMM14 /* m[13], m[11] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 64(DX), X13 // X13 = m[8]+ m[9] - MOVOU 112(DX), X14 // X14 = m[14]+m[15] - LONG $0x6d1141c4; BYTE $0xd4 // VPUNPCKHQDQ XMM10, XMM13, XMM12 /* m[9], m[1] */ - LONG $0x6c0141c4; BYTE $0xde // VPUNPCKLQDQ XMM11, XMM15, XMM14 /* m[12], m[14] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d1141c4; BYTE $0xc5 // VPUNPCKHQDQ XMM8, XMM13, XMM13 /* ___, m[5] */ - LONG $0x6c1941c4; BYTE $0xc0 // VPUNPCKLQDQ XMM8, XMM12, XMM8 /* m[2], ____ */ - LONG $0x6d0141c4; BYTE $0xcf // VPUNPCKHQDQ XMM9, XMM15, XMM15 /* ___, m[15] */ - LONG $0x6c1141c4; BYTE $0xc9 // VPUNPCKLQDQ XMM9, XMM13, XMM9 /* m[4], ____ */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X15 // X15 = m[8]+ m[9] - LONG $0x6c1141c4; BYTE $0xd6 // VPUNPCKLQDQ XMM10, XMM13, XMM14 /* m[6], m[10] */ - LONG $0x6c1941c4; BYTE $0xdf // VPUNPCKLQDQ XMM11, XMM12, XMM15 /* m[0], m[8] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 5 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - LONG $0x6d0941c4; BYTE $0xc5 // VPUNPCKHQDQ XMM8, XMM14, XMM13 /* m[9], m[5] */ - LONG $0x6c1941c4; BYTE $0xcf // VPUNPCKLQDQ XMM9, XMM12, XMM15 /* m[2], m[10] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0941c4; BYTE $0xd6 // VPUNPCKHQDQ XMM10, XMM14, XMM14 /* ___, m[7] */ - LONG $0x6c1941c4; BYTE $0xd2 // VPUNPCKLQDQ XMM10, XMM12, XMM10 /* m[0], ____ */ - LONG $0x6d0141c4; BYTE $0xdf // VPUNPCKHQDQ XMM11, XMM15, XMM15 /* ___, m[15] */ - LONG $0x6c1141c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM13, XMM11 /* m[4], ____ */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0941c4; BYTE $0xc6 // VPUNPCKHQDQ XMM8, XMM14, XMM14 /* ___, m[11] */ - LONG $0x6c0141c4; BYTE $0xc0 // VPUNPCKLQDQ XMM8, XMM15, XMM8 /* m[14], ____ */ - LONG $0x6d1941c4; BYTE $0xcc // VPUNPCKHQDQ XMM9, XMM12, XMM12 /* ___, m[3] */ - LONG $0x6c1141c4; BYTE $0xc9 // VPUNPCKLQDQ XMM9, XMM13, XMM9 /* m[6], ____ */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 64(DX), X13 // X13 = m[8]+ m[9] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - LONG $0x0f0943c4; WORD $0x08d4 // VPALIGNR XMM10, XMM14, XMM12, 0x8 /* m[1], m[12] */ - LONG $0x6d0941c4; BYTE $0xde // VPUNPCKHQDQ XMM11, XMM14, XMM14 /* ___, m[13] */ - LONG $0x6c1141c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM13, XMM11 /* m[8], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 6 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 64(DX), X15 // X15 = m[8]+ m[9] - LONG $0x6c1141c4; BYTE $0xc6 // VPUNPCKLQDQ XMM8, XMM13, XMM14 /* m[2], m[6] */ - LONG $0x6c1941c4; BYTE $0xcf // VPUNPCKLQDQ XMM9, XMM12, XMM15 /* m[0], m[8] */ - MOVOU 80(DX), X12 // X12 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - LONG $0x6c0941c4; BYTE $0xd4 // VPUNPCKLQDQ XMM10, XMM14, XMM12 /* m[12], m[10] */ - LONG $0x6d1941c4; BYTE $0xdd // VPUNPCKHQDQ XMM11, XMM12, XMM13 /* m[11], m[3] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0941c4; BYTE $0xc6 // VPUNPCKHQDQ XMM8, XMM14, XMM14 /* ___, m[7] */ - LONG $0x6c1141c4; BYTE $0xc0 // VPUNPCKLQDQ XMM8, XMM13, XMM8 /* m[4], ____ */ - LONG $0x6d0141c4; BYTE $0xcc // VPUNPCKHQDQ XMM9, XMM15, XMM12 /* m[15], m[1] */ - MOVOU 64(DX), X12 // X12 = m[8]+ m[9] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - LONG $0x6d0941c4; BYTE $0xd5 // VPUNPCKHQDQ XMM10, XMM14, XMM13 /* m[13], m[5] */ - LONG $0x6d1941c4; BYTE $0xdc // VPUNPCKHQDQ XMM11, XMM12, XMM12 /* ___, m[9] */ - LONG $0x6c0141c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM15, XMM11 /* m[14], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 7 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d1941c4; BYTE $0xc4 // VPUNPCKHQDQ XMM8, XMM12, XMM12 /* ___, m[1] */ - LONG $0x6c0941c4; BYTE $0xc0 // VPUNPCKLQDQ XMM8, XMM14, XMM8 /* m[12], ____ */ - LONG $0x6c0141c4; BYTE $0xcd // VPUNPCKLQDQ XMM9, XMM15, XMM13 /* m[14], m[4] */ - MOVOU 80(DX), X12 // X12 = m[10]+m[11] - LONG $0x6d1141c4; BYTE $0xd7 // VPUNPCKHQDQ XMM10, XMM13, XMM15 /* m[5], m[15] */ - LONG $0x0f1943c4; WORD $0x08de // VPALIGNR XMM11, XMM12, XMM14, 0x8 /* m[13], m[10] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[0], m[6] */ - LONG $0x0f0943c4; WORD $0x08ce // VPALIGNR XMM9, XMM14, XMM14, 0x8 /* m[9], m[8] */ - MOVOU 16(DX), X14 // X14 = m[2]+ m[3] - LONG $0x6d1141c4; BYTE $0xd6 // VPUNPCKHQDQ XMM10, XMM13, XMM14 /* m[7], m[3] */ - LONG $0x6d0141c4; BYTE $0xdf // VPUNPCKHQDQ XMM11, XMM15, XMM15 /* ___, m[11] */ - LONG $0x6c0941c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM14, XMM11 /* m[2], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 8 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0941c4; BYTE $0xc5 // VPUNPCKHQDQ XMM8, XMM14, XMM13 /* m[13], m[7] */ - LONG $0x6d1941c4; BYTE $0xcc // VPUNPCKHQDQ XMM9, XMM12, XMM12 /* ___, m[3] */ - LONG $0x6c0941c4; BYTE $0xc9 // VPUNPCKLQDQ XMM9, XMM14, XMM9 /* m[12], ____ */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 64(DX), X13 // X13 = m[8]+ m[9] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - LONG $0x0f0143c4; WORD $0x08d6 // VPALIGNR XMM10, XMM15, XMM14, 0x8 /* m[11], m[14] */ - LONG $0x6d1941c4; BYTE $0xdd // VPUNPCKHQDQ XMM11, XMM12, XMM13 /* m[1], m[9] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d1141c4; BYTE $0xc7 // VPUNPCKHQDQ XMM8, XMM13, XMM15 /* m[5], m[15] */ - LONG $0x6c0941c4; BYTE $0xcc // VPUNPCKLQDQ XMM9, XMM14, XMM12 /* m[8], m[2] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - LONG $0x6c1941c4; BYTE $0xd5 // VPUNPCKLQDQ XMM10, XMM12, XMM13 /* m[0], m[4] */ - LONG $0x6c0941c4; BYTE $0xdf // VPUNPCKLQDQ XMM11, XMM14, XMM15 /* m[6], m[10] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 9 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6c1141c4; BYTE $0xc7 // VPUNPCKLQDQ XMM8, XMM13, XMM15 /* m[6], m[14] */ - LONG $0x0f1943c4; WORD $0x08ce // VPALIGNR XMM9, XMM12, XMM14, 0x8 /* m[11], m[0] */ - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - LONG $0x6d0141c4; BYTE $0xd6 // VPUNPCKHQDQ XMM10, XMM15, XMM14 /* m[15], m[9] */ - LONG $0x0f0943c4; WORD $0x08dd // VPALIGNR XMM11, XMM14, XMM13, 0x8 /* m[3], m[8] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - LONG $0x6d0141c4; BYTE $0xc7 // VPUNPCKHQDQ XMM8, XMM15, XMM15 /* ___, m[13] */ - LONG $0x6c0141c4; BYTE $0xc0 // VPUNPCKLQDQ XMM8, XMM15, XMM8 /* m[12], ____ */ - LONG $0x0f0943c4; WORD $0x08cc // VPALIGNR XMM9, XMM14, XMM12, 0x8 /* m[1], m[10] */ - MOVOU 32(DX), X12 // X12 = m[4]+ m[5] - MOVOU 48(DX), X15 // X15 = m[6]+ m[7] - LONG $0x6d0141c4; BYTE $0xd7 // VPUNPCKHQDQ XMM10, XMM15, XMM15 /* ___, m[7] */ - LONG $0x6c1141c4; BYTE $0xd2 // VPUNPCKLQDQ XMM10, XMM13, XMM10 /* m[2], ____ */ - LONG $0x6d1941c4; BYTE $0xdc // VPUNPCKHQDQ XMM11, XMM12, XMM12 /* ___, m[5] */ - LONG $0x6c1941c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM12, XMM11 /* m[4], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 0 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - LONG $0x6c0141c4; BYTE $0xc6 // VPUNPCKLQDQ XMM8, XMM15, XMM14 /* m[10], m[8] */ - LONG $0x6d1141c4; BYTE $0xcc // VPUNPCKHQDQ XMM9, XMM13, XMM12 /* m[7], m[1] */ - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X14 // X14 = m[4]+ m[5] - LONG $0x6c1941c4; BYTE $0xd6 // VPUNPCKLQDQ XMM10, XMM12, XMM14 /* m[2], m[4] */ - LONG $0x6d0941c4; BYTE $0xde // VPUNPCKHQDQ XMM11, XMM14, XMM14 /* ___, m[5] */ - LONG $0x6c1141c4; BYTE $0xdb // VPUNPCKLQDQ XMM11, XMM13, XMM11 /* m[6], ____ */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 64(DX), X13 // X13 = m[8]+ m[9] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0141c4; BYTE $0xc5 // VPUNPCKHQDQ XMM8, XMM15, XMM13 /* m[15], m[9] */ - LONG $0x6d1941c4; BYTE $0xce // VPUNPCKHQDQ XMM9, XMM12, XMM14 /* m[3], m[13] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - LONG $0x0f0143c4; WORD $0x08d5 // VPALIGNR XMM10, XMM15, XMM13, 0x8 /* m[11], m[14] */ - LONG $0x6c0941c4; BYTE $0xdc // VPUNPCKLQDQ XMM11, XMM14, XMM12 /* m[12], m[0] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 1 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+m[1] - MOVOU 16(DX), X13 // X13 = m[2]+m[3] - MOVOU 32(DX), X14 // X14 = m[4]+m[5] - MOVOU 48(DX), X15 // X15 = m[6]+m[7] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[0], m[2] */ - LONG $0x6c0941c4; BYTE $0xcf // VPUNPCKLQDQ XMM9, XMM14, XMM15 /* m[4], m[6] */ - LONG $0x6d1941c4; BYTE $0xd5 // VPUNPCKHQDQ XMM10, XMM12, XMM13 /* m[1], m[3] */ - LONG $0x6d0941c4; BYTE $0xdf // VPUNPCKHQDQ XMM11, XMM14, XMM15 /* m[5], m[7] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 64(DX), X12 // X12 = m[8]+ m[9] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[8],m[10] */ - LONG $0x6c0941c4; BYTE $0xcf // VPUNPCKLQDQ XMM9, XMM14, XMM15 /* m[12],m[14] */ - LONG $0x6d1941c4; BYTE $0xd5 // VPUNPCKHQDQ XMM10, XMM12, XMM13 /* m[9],m[11] */ - LONG $0x6d0941c4; BYTE $0xdf // VPUNPCKHQDQ XMM11, XMM14, XMM15 /* m[13],m[15] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 2 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 112(DX), X12 // X12 = m[14]+m[15] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - LONG $0x6c1941c4; BYTE $0xc5 // VPUNPCKLQDQ XMM8, XMM12, XMM13 /* m[14], m[4] */ - LONG $0x6d0941c4; BYTE $0xcf // VPUNPCKHQDQ XMM9, XMM14, XMM15 /* m[9], m[13] */ - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 48(DX), X15 // X15 = m[6]+ m[7] - LONG $0x6c1141c4; BYTE $0xd6 // VPUNPCKLQDQ XMM10, XMM13, XMM14 /* m[10], m[8] */ - LONG $0x0f0143c4; WORD $0x08dc // VPALIGNR XMM11, XMM15, XMM12, 0x8 /* m[15], m[6] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - LONG $0x0f1943c4; WORD $0x08c4 // VPALIGNR XMM8, XMM12, XMM12, 0x8 /* m[1], m[0] */ - LONG $0x6d0941c4; BYTE $0xcd // VPUNPCKHQDQ XMM9, XMM14, XMM13 /* m[11], m[5] */ - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - LONG $0x6c0941c4; BYTE $0xd4 // VPUNPCKLQDQ XMM10, XMM14, XMM12 /* m[12], m[2] */ - LONG $0x6d1141c4; BYTE $0xdc // VPUNPCKHQDQ XMM11, XMM13, XMM12 /* m[7], m[3] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - // Reload digest (most current value store in &out) - MOVQ out+144(FP), SI // SI: &in - MOVOU 0(SI), X12 // X12 = in[0]+in[1] /* row1l = LOAD( &S->h[0] ); */ - MOVOU 16(SI), X13 // X13 = in[2]+in[3] /* row1h = LOAD( &S->h[2] ); */ - MOVOU 32(SI), X14 // X14 = in[4]+in[5] /* row2l = LOAD( &S->h[4] ); */ - MOVOU 48(SI), X15 // X15 = in[6]+in[7] /* row2h = LOAD( &S->h[6] ); */ - - // Final computations and prepare for storing - PXOR X4, X0 // X0 = X0 ^ X4 /* row1l = _mm_xor_si128( row3l, row1l ); */ - PXOR X5, X1 // X1 = X1 ^ X5 /* row1h = _mm_xor_si128( row3h, row1h ); */ - PXOR X12, X0 // X0 = X0 ^ X12 /* STORE( &S->h[0], _mm_xor_si128( LOAD( &S->h[0] ), row1l ) ); */ - PXOR X13, X1 // X1 = X1 ^ X13 /* STORE( &S->h[2], _mm_xor_si128( LOAD( &S->h[2] ), row1h ) ); */ - PXOR X6, X2 // X2 = X2 ^ X6 /* row2l = _mm_xor_si128( row4l, row2l ); */ - PXOR X7, X3 // X3 = X3 ^ X7 /* row2h = _mm_xor_si128( row4h, row2h ); */ - PXOR X14, X2 // X2 = X2 ^ X14 /* STORE( &S->h[4], _mm_xor_si128( LOAD( &S->h[4] ), row2l ) ); */ - PXOR X15, X3 // X3 = X3 ^ X15 /* STORE( &S->h[6], _mm_xor_si128( LOAD( &S->h[6] ), row2h ) ); */ - - // Store digest into &out - MOVQ out+144(FP), SI // SI: &out - MOVOU X0, 0(SI) // out[0]+out[1] = X0 - MOVOU X1, 16(SI) // out[2]+out[3] = X1 - MOVOU X2, 32(SI) // out[4]+out[5] = X2 - MOVOU X3, 48(SI) // out[6]+out[7] = X3 - - // Increment message pointer and check if there's more to do - ADDQ $128, DX // message += 128 - SUBQ $1, R8 - JNZ loop - -complete: - RET diff --git a/vendor/github.com/minio/blake2b-simd/compressSse_amd64.go b/vendor/github.com/minio/blake2b-simd/compressSse_amd64.go deleted file mode 100644 index d539a7ade..000000000 --- a/vendor/github.com/minio/blake2b-simd/compressSse_amd64.go +++ /dev/null @@ -1,41 +0,0 @@ -//+build !noasm -//+build !appengine - -/* - * Minio Cloud Storage, (C) 2016 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 blake2b - -//go:noescape -func blockSSELoop(p []uint8, in, iv, t, f, shffle, out []uint64) - -func compressSSE(d *digest, p []uint8) { - var ( - in [8]uint64 - out [8]uint64 - shffle [2]uint64 - ) - - // vector for PSHUFB instruction - shffle[0] = 0x0201000706050403 - shffle[1] = 0x0a09080f0e0d0c0b - - in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7] = d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] - - blockSSELoop(p, in[:], iv[:], d.t[:], d.f[:], shffle[:], out[:]) - - d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] = out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7] -} diff --git a/vendor/github.com/minio/blake2b-simd/compressSse_amd64.s b/vendor/github.com/minio/blake2b-simd/compressSse_amd64.s deleted file mode 100644 index 6f31c949e..000000000 --- a/vendor/github.com/minio/blake2b-simd/compressSse_amd64.s +++ /dev/null @@ -1,770 +0,0 @@ -//+build !noasm !appengine - -// -// Minio Cloud Storage, (C) 2016 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. -// - -// -// Based on SSE implementation from https://github.com/BLAKE2/BLAKE2/blob/master/sse/blake2b.c -// -// Use github.com/fwessels/asm2plan9s on this file to assemble instructions to their Plan9 equivalent -// -// Assembly code below essentially follows the ROUND macro (see blake2b-round.h) which is defined as: -// #define ROUND(r) \ -// LOAD_MSG_ ##r ##_1(b0, b1); \ -// G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// LOAD_MSG_ ##r ##_2(b0, b1); \ -// G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ -// LOAD_MSG_ ##r ##_3(b0, b1); \ -// G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// LOAD_MSG_ ##r ##_4(b0, b1); \ -// G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ -// UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); -// -// as well as the go equivalent in https://github.com/dchest/blake2b/blob/master/block.go -// -// As in the macro, G1/G2 in the 1st and 2nd half are identical (so literal copy of assembly) -// -// Rounds are also the same, except for the loading of the message (and rounds 1 & 11 and -// rounds 2 & 12 are identical) -// - -#define G1 \ - \ // G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); - LONG $0xd40f4166; BYTE $0xc0 \ // PADDQ XMM0,XMM8 /* v0 += m[0], v1 += m[2] */ - LONG $0xd40f4166; BYTE $0xc9 \ // PADDQ XMM1,XMM9 /* v2 += m[4], v3 += m[6] */ - LONG $0xc2d40f66 \ // PADDQ XMM0,XMM2 /* v0 += v4, v1 += v5 */ - LONG $0xcbd40f66 \ // PADDQ XMM1,XMM3 /* v2 += v6, v3 += v7 */ - LONG $0xf0ef0f66 \ // PXOR XMM6,XMM0 /* v12 ^= v0, v13 ^= v1 */ - LONG $0xf9ef0f66 \ // PXOR XMM7,XMM1 /* v14 ^= v2, v15 ^= v3 */ - LONG $0xf6700f66; BYTE $0xb1 \ // PSHUFD XMM6,XMM6,0xb1 /* v12 = v12<<(64-32) | v12>>32, v13 = v13<<(64-32) | v13>>32 */ - LONG $0xff700f66; BYTE $0xb1 \ // PSHUFD XMM7,XMM7,0xb1 /* v14 = v14<<(64-32) | v14>>32, v15 = v15<<(64-32) | v15>>32 */ - LONG $0xe6d40f66 \ // PADDQ XMM4,XMM6 /* v8 += v12, v9 += v13 */ - LONG $0xefd40f66 \ // PADDQ XMM5,XMM7 /* v10 += v14, v11 += v15 */ - LONG $0xd4ef0f66 \ // PXOR XMM2,XMM4 /* v4 ^= v8, v5 ^= v9 */ - LONG $0xddef0f66 \ // PXOR XMM3,XMM5 /* v6 ^= v10, v7 ^= v11 */ - LONG $0x380f4166; WORD $0xd400 \ // PSHUFB XMM2,XMM12 /* v4 = v4<<(64-24) | v4>>24, v5 = v5<<(64-24) | v5>>24 */ - LONG $0x380f4166; WORD $0xdc00 // PSHUFB XMM3,XMM12 /* v6 = v6<<(64-24) | v6>>24, v7 = v7<<(64-24) | v7>>24 */ - -#define G2 \ - \ // G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); - LONG $0xd40f4166; BYTE $0xc2 \ // PADDQ XMM0,XMM10 /* v0 += m[1], v1 += m[3] */ - LONG $0xd40f4166; BYTE $0xcb \ // PADDQ XMM1,XMM11 /* v2 += m[5], v3 += m[7] */ - LONG $0xc2d40f66 \ // PADDQ XMM0,XMM2 /* v0 += v4, v1 += v5 */ - LONG $0xcbd40f66 \ // PADDQ XMM1,XMM3 /* v2 += v6, v3 += v7 */ - LONG $0xf0ef0f66 \ // PXOR XMM6,XMM0 /* v12 ^= v0, v13 ^= v1 */ - LONG $0xf9ef0f66 \ // PXOR XMM7,XMM1 /* v14 ^= v2, v15 ^= v3 */ - LONG $0xf6700ff2; BYTE $0x39 \ // PSHUFLW XMM6,XMM6,0x39 /* combined with next ... */ - LONG $0xf6700ff3; BYTE $0x39 \ // PSHUFHW XMM6,XMM6,0x39 /* v12 = v12<<(64-16) | v12>>16, v13 = v13<<(64-16) | v13>>16 */ - LONG $0xff700ff2; BYTE $0x39 \ // PSHUFLW XMM7,XMM7,0x39 /* combined with next ... */ - LONG $0xff700ff3; BYTE $0x39 \ // PSHUFHW XMM7,XMM7,0x39 /* v14 = v14<<(64-16) | v14>>16, v15 = v15<<(64-16) | v15>>16 */ - LONG $0xe6d40f66 \ // PADDQ XMM4,XMM6 /* v8 += v12, v9 += v13 */ - LONG $0xefd40f66 \ // PADDQ XMM5,XMM7 /* v10 += v14, v11 += v15 */ - LONG $0xd4ef0f66 \ // PXOR XMM2,XMM4 /* v4 ^= v8, v5 ^= v9 */ - LONG $0xddef0f66 \ // PXOR XMM3,XMM5 /* v6 ^= v10, v7 ^= v11 */ - MOVOU X2, X15 \ - LONG $0xd40f4466; BYTE $0xfa \ // PADDQ XMM15,XMM2 /* temp reg = reg*2 */ - LONG $0xd2730f66; BYTE $0x3f \ // PSRLQ XMM2,0x3f /* reg = reg>>63 */ - LONG $0xef0f4166; BYTE $0xd7 \ // PXOR XMM2,XMM15 /* ORed together: v4 = v4<<(64-63) | v4>>63, v5 = v5<<(64-63) | v5>>63 */ - MOVOU X3, X15 \ - LONG $0xd40f4466; BYTE $0xfb \ // PADDQ XMM15,XMM3 /* temp reg = reg*2 */ - LONG $0xd3730f66; BYTE $0x3f \ // PSRLQ XMM3,0x3f /* reg = reg>>63 */ - LONG $0xef0f4166; BYTE $0xdf // PXOR XMM3,XMM15 /* ORed together: v6 = v6<<(64-63) | v6>>63, v7 = v7<<(64-63) | v7>>63 */ - -#define DIAGONALIZE \ - \ // DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); - MOVOU X6, X13 \ /* t0 = row4l;\ */ - MOVOU X2, X14 \ /* t1 = row2l;\ */ - MOVOU X4, X6 \ /* row4l = row3l;\ */ - MOVOU X5, X4 \ /* row3l = row3h;\ */ - MOVOU X6, X5 \ /* row3h = row4l;\ */ - LONG $0x6c0f4566; BYTE $0xfd \ // PUNPCKLQDQ XMM15, XMM13 /* _mm_unpacklo_epi64(t0, t0) */ - MOVOU X7, X6 \ - LONG $0x6d0f4166; BYTE $0xf7 \ // PUNPCKHQDQ XMM6, XMM15 /* row4l = _mm_unpackhi_epi64(row4h, ); \ */ - LONG $0x6c0f4466; BYTE $0xff \ // PUNPCKLQDQ XMM15, XMM7 /* _mm_unpacklo_epi64(row4h, row4h) */ - MOVOU X13, X7 \ - LONG $0x6d0f4166; BYTE $0xff \ // PUNPCKHQDQ XMM7, XMM15 /* row4h = _mm_unpackhi_epi64(t0, ); \ */ - LONG $0x6c0f4466; BYTE $0xfb \ // PUNPCKLQDQ XMM15, XMM3 /* _mm_unpacklo_epi64(row2h, row2h) */ - LONG $0x6d0f4166; BYTE $0xd7 \ // PUNPCKHQDQ XMM2, XMM15 /* row2l = _mm_unpackhi_epi64(row2l, ); \ */ - LONG $0x6c0f4566; BYTE $0xfe \ // PUNPCKLQDQ XMM15, XMM14 /* _mm_unpacklo_epi64(t1, t1) */ - LONG $0x6d0f4166; BYTE $0xdf // PUNPCKHQDQ XMM3, XMM15 /* row2h = _mm_unpackhi_epi64(row2h, ) */ - -#define UNDIAGONALIZE \ - \ // UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); - MOVOU X4, X13 \ /* t0 = row3l;\ */ - MOVOU X5, X4 \ /* row3l = row3h;\ */ - MOVOU X13, X5 \ /* row3h = t0;\ */ - MOVOU X2, X13 \ /* t0 = row2l;\ */ - MOVOU X6, X14 \ /* t1 = row4l;\ */ - LONG $0x6c0f4466; BYTE $0xfa \ // PUNPCKLQDQ XMM15, XMM2 /* _mm_unpacklo_epi64(row2l, row2l) */ - MOVOU X3, X2 \ - LONG $0x6d0f4166; BYTE $0xd7 \ // PUNPCKHQDQ XMM2, XMM15 /* row2l = _mm_unpackhi_epi64(row2h, ); \ */ - LONG $0x6c0f4466; BYTE $0xfb \ // PUNPCKLQDQ XMM15, XMM3 /* _mm_unpacklo_epi64(row2h, row2h) */ - MOVOU X13, X3 \ - LONG $0x6d0f4166; BYTE $0xdf \ // PUNPCKHQDQ XMM3, XMM15 /* row2h = _mm_unpackhi_epi64(t0, ); \ */ - LONG $0x6c0f4466; BYTE $0xff \ // PUNPCKLQDQ XMM15, XMM7 /* _mm_unpacklo_epi64(row4h, row4h) */ - LONG $0x6d0f4166; BYTE $0xf7 \ // PUNPCKHQDQ XMM6, XMM15 /* row4l = _mm_unpackhi_epi64(row4l, ); \ */ - LONG $0x6c0f4566; BYTE $0xfe \ // PUNPCKLQDQ XMM15, XMM14 /* _mm_unpacklo_epi64(t1, t1) */ - LONG $0x6d0f4166; BYTE $0xff // PUNPCKHQDQ XMM7, XMM15 /* row4h = _mm_unpackhi_epi64(row4h, ) */ - -#define LOAD_SHUFFLE \ - \ // Load shuffle value - MOVQ shffle+120(FP), SI \ // SI: &shuffle - MOVOU 0(SI), X12 // X12 = 03040506 07000102 0b0c0d0e 0f08090a - -// func blockSSELoop(p []uint8, in, iv, t, f, shffle, out []uint64) -TEXT ·blockSSELoop(SB), 7, $0 - // REGISTER USE - // R8: loop counter - // DX: message pointer - // SI: temp pointer for loading - // X0 - X7: v0 - v15 - // X8 - X11: m[0] - m[7] - // X12: shuffle value - // X13 - X15: temp registers - - // Load digest - MOVQ in+24(FP), SI // SI: &in - MOVOU 0(SI), X0 // X0 = in[0]+in[1] /* row1l = LOAD( &S->h[0] ); */ - MOVOU 16(SI), X1 // X1 = in[2]+in[3] /* row1h = LOAD( &S->h[2] ); */ - MOVOU 32(SI), X2 // X2 = in[4]+in[5] /* row2l = LOAD( &S->h[4] ); */ - MOVOU 48(SI), X3 // X3 = in[6]+in[7] /* row2h = LOAD( &S->h[6] ); */ - - // Already store digest into &out (so we can reload it later generically) - MOVQ out+144(FP), SI // SI: &out - MOVOU X0, 0(SI) // out[0]+out[1] = X0 - MOVOU X1, 16(SI) // out[2]+out[3] = X1 - MOVOU X2, 32(SI) // out[4]+out[5] = X2 - MOVOU X3, 48(SI) // out[6]+out[7] = X3 - - // Initialize message pointer and loop counter - MOVQ message+0(FP), DX // DX: &p (message) - MOVQ message_len+8(FP), R8 // R8: len(message) - SHRQ $7, R8 // len(message) / 128 - CMPQ R8, $0 - JEQ complete - -loop: - // Increment counter - MOVQ t+72(FP), SI // SI: &t - MOVQ 0(SI), R9 - ADDQ $128, R9 // /* d.t[0] += BlockSize */ - MOVQ R9, 0(SI) - CMPQ R9, $128 // /* if d.t[0] < BlockSize { */ - JGE noincr - MOVQ 8(SI), R9 - ADDQ $1, R9 // /* d.t[1]++ */ - MOVQ R9, 8(SI) - -noincr: // /* } */ - - // Load initialization vector - MOVQ iv+48(FP), SI // SI: &iv - MOVOU 0(SI), X4 // X4 = iv[0]+iv[1] /* row3l = LOAD( &blake2b_IV[0] ); */ - MOVOU 16(SI), X5 // X5 = iv[2]+iv[3] /* row3h = LOAD( &blake2b_IV[2] ); */ - MOVOU 32(SI), X6 // X6 = iv[4]+iv[5] /* LOAD( &blake2b_IV[4] ) */ - MOVOU 48(SI), X7 // X7 = iv[6]+iv[7] /* LOAD( &blake2b_IV[6] ) */ - MOVQ t+72(FP), SI // SI: &t - MOVOU 0(SI), X8 // X8 = t[0]+t[1] /* LOAD( &S->t[0] ) */ - PXOR X8, X6 // X6 = X6 ^ X8 /* row4l = _mm_xor_si128( , ); */ - MOVQ t+96(FP), SI // SI: &f - MOVOU 0(SI), X8 // X8 = f[0]+f[1] /* LOAD( &S->f[0] ) */ - PXOR X8, X7 // X7 = X7 ^ X8 /* row4h = _mm_xor_si128( , ); */ - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+m[1] - MOVOU 16(DX), X13 // X13 = m[2]+m[3] - MOVOU 32(DX), X14 // X14 = m[4]+m[5] - MOVOU 48(DX), X15 // X15 = m[6]+m[7] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[0], m[2] */ - MOVOU X14, X9 - LONG $0x6c0f4566; BYTE $0xcf // PUNPCKLQDQ XMM9, XMM15 /* m[4], m[6] */ - MOVOU X12, X10 - LONG $0x6d0f4566; BYTE $0xd5 // PUNPCKHQDQ XMM10, XMM13 /* m[1], m[3] */ - MOVOU X14, X11 - LONG $0x6d0f4566; BYTE $0xdf // PUNPCKHQDQ XMM11, XMM15 /* m[5], m[7] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 64(DX), X12 // X12 = m[8]+ m[9] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[8],m[10] */ - MOVOU X14, X9 - LONG $0x6c0f4566; BYTE $0xcf // PUNPCKLQDQ XMM9, XMM15 /* m[12],m[14] */ - MOVOU X12, X10 - LONG $0x6d0f4566; BYTE $0xd5 // PUNPCKHQDQ XMM10, XMM13 /* m[9],m[11] */ - MOVOU X14, X11 - LONG $0x6d0f4566; BYTE $0xdf // PUNPCKHQDQ XMM11, XMM15 /* m[13],m[15] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 2 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 112(DX), X12 // X12 = m[14]+m[15] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[14], m[4] */ - MOVOU X14, X9 - LONG $0x6d0f4566; BYTE $0xcf // PUNPCKHQDQ XMM9, XMM15 /* m[9], m[13] */ - MOVOU 80(DX), X10 // X10 = m[10]+m[11] - MOVOU 48(DX), X11 // X11 = m[6]+ m[7] - LONG $0x6c0f4566; BYTE $0xd6 // PUNPCKLQDQ XMM10, XMM14 /* m[10], m[8] */ - LONG $0x3a0f4566; WORD $0xdc0f; BYTE $0x08 // PALIGNR XMM11, XMM12, 0x8 /* m[15], m[6] */; ; ; ; ; - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU X12, X8 - LONG $0x3a0f4566; WORD $0xc40f; BYTE $0x08 // PALIGNR XMM8, XMM12, 0x8 /* m[1], m[0] */ - MOVOU X14, X9 - LONG $0x6d0f4566; BYTE $0xcd // PUNPCKHQDQ XMM9, XMM13 /* m[11], m[5] */ - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X11 // X11 = m[6]+ m[7] - MOVOU 96(DX), X10 // X10 = m[12]+m[13] - LONG $0x6c0f4566; BYTE $0xd4 // PUNPCKLQDQ XMM10, XMM12 /* m[12], m[2] */ - LONG $0x6d0f4566; BYTE $0xdc // PUNPCKHQDQ XMM11, XMM12 /* m[7], m[3] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 3 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 32(DX), X12 // X12 = m[4]+ m[5] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X14, X8 - LONG $0x3a0f4566; WORD $0xc50f; BYTE $0x08 // PALIGNR XMM8, XMM13, 0x8 /* m[11], m[12] */ - MOVOU X12, X9 - LONG $0x6d0f4566; BYTE $0xcf // PUNPCKHQDQ XMM9, XMM15 /* m[5], m[15] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 64(DX), X10 // X10 = m[8]+ m[9] - LONG $0x6c0f4566; BYTE $0xd4 // PUNPCKLQDQ XMM10, XMM12 /* m[8], m[0] */ - LONG $0x6d0f4566; BYTE $0xf6 // PUNPCKHQDQ XMM14, XMM14 /* ___, m[13] */ - MOVOU X13, X11 - LONG $0x6c0f4566; BYTE $0xde // PUNPCKLQDQ XMM11, XMM14 /* m[2], ___ */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - MOVOU X12, X9 - LONG $0x6d0f4566; BYTE $0xcc // PUNPCKHQDQ XMM9, XMM12 /* ___, m[3] */ - MOVOU X15, X8 - LONG $0x6c0f4566; BYTE $0xc1 // PUNPCKLQDQ XMM8, XMM9 /* m[10], ___ */ - MOVOU X13, X9 - LONG $0x6d0f4566; BYTE $0xce // PUNPCKHQDQ XMM9, XMM14 /* m[7], m[9] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X11 // X11 = m[4]+ m[5] - MOVOU 112(DX), X10 // X10 = m[14]+m[15] - LONG $0x6c0f4566; BYTE $0xd5 // PUNPCKLQDQ XMM10, XMM13 /* m[14], m[6] */ - LONG $0x3a0f4566; WORD $0xdc0f; BYTE $0x08 // PALIGNR XMM11, XMM12, 0x8 /* m[1], m[4] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 4 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - MOVOU X13, X8 - LONG $0x6d0f4566; BYTE $0xc4 // PUNPCKHQDQ XMM8, XMM12 /* m[7], m[3] */ - MOVOU X15, X9 - LONG $0x6d0f4566; BYTE $0xce // PUNPCKHQDQ XMM9, XMM14 /* m[13], m[11] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 64(DX), X10 // X10 = m[8]+ m[9] - MOVOU 112(DX), X14 // X14 = m[14]+m[15] - LONG $0x6d0f4566; BYTE $0xd4 // PUNPCKHQDQ XMM10, XMM12 /* m[9], m[1] */ - MOVOU X15, X11 - LONG $0x6c0f4566; BYTE $0xde // PUNPCKLQDQ XMM11, XMM14 /* m[12], m[14] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X13, X9 - LONG $0x6d0f4566; BYTE $0xcd // PUNPCKHQDQ XMM9, XMM13 /* ___, m[5] */ - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc1 // PUNPCKLQDQ XMM8, XMM9 /* m[2], ____ */ - MOVOU X15, X10 - LONG $0x6d0f4566; BYTE $0xd7 // PUNPCKHQDQ XMM10, XMM15 /* ___, m[15] */ - MOVOU X13, X9 - LONG $0x6c0f4566; BYTE $0xca // PUNPCKLQDQ XMM9, XMM10 /* m[4], ____ */ - MOVOU 0(DX), X11 // X11 = m[0]+ m[1] - MOVOU 48(DX), X10 // X10 = m[6]+ m[7] - MOVOU 64(DX), X15 // X15 = m[8]+ m[9] - LONG $0x6c0f4566; BYTE $0xd6 // PUNPCKLQDQ XMM10, XMM14 /* m[6], m[10] */ - LONG $0x6c0f4566; BYTE $0xdf // PUNPCKLQDQ XMM11, XMM15 /* m[0], m[8] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 5 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - MOVOU X14, X8 - LONG $0x6d0f4566; BYTE $0xc5 // PUNPCKHQDQ XMM8, XMM13 /* m[9], m[5] */ - MOVOU X12, X9 - LONG $0x6c0f4566; BYTE $0xcf // PUNPCKLQDQ XMM9, XMM15 /* m[2], m[10] */ - MOVOU 0(DX), X10 // X10 = m[0]+ m[1] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0f4566; BYTE $0xf6 // PUNPCKHQDQ XMM14, XMM14 /* ___, m[7] */ - LONG $0x6c0f4566; BYTE $0xd6 // PUNPCKLQDQ XMM10, XMM14 /* m[0], ____ */ - LONG $0x6d0f4566; BYTE $0xff // PUNPCKHQDQ XMM15, XMM15 /* ___, m[15] */ - MOVOU X13, X11 - LONG $0x6c0f4566; BYTE $0xdf // PUNPCKLQDQ XMM11, XMM15 /* m[4], ____ */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - LONG $0x6d0f4566; BYTE $0xf6 // PUNPCKHQDQ XMM14, XMM14 /* ___, m[11] */ - MOVOU X15, X8 - LONG $0x6c0f4566; BYTE $0xc6 // PUNPCKLQDQ XMM8, XMM14 /* m[14], ____ */ - LONG $0x6d0f4566; BYTE $0xe4 // PUNPCKHQDQ XMM12, XMM12 /* ___, m[3] */ - MOVOU X13, X9 - LONG $0x6c0f4566; BYTE $0xcc // PUNPCKLQDQ XMM9, XMM12 /* m[6], ____ */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 64(DX), X11 // X11 = m[8]+ m[9] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU X14, X10 - LONG $0x3a0f4566; WORD $0xd40f; BYTE $0x08 // PALIGNR XMM10, XMM12, 0x8 /* m[1], m[12] */ - LONG $0x6d0f4566; BYTE $0xf6 // PUNPCKHQDQ XMM14, XMM14 /* ___, m[13] */ - LONG $0x6c0f4566; BYTE $0xde // PUNPCKLQDQ XMM11, XMM14 /* m[8], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 6 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 64(DX), X15 // X15 = m[8]+ m[9] - MOVOU X13, X8 - LONG $0x6c0f4566; BYTE $0xc6 // PUNPCKLQDQ XMM8, XMM14 /* m[2], m[6] */ - MOVOU X12, X9 - LONG $0x6c0f4566; BYTE $0xcf // PUNPCKLQDQ XMM9, XMM15 /* m[0], m[8] */ - MOVOU 80(DX), X12 // X12 = m[10]+m[11] - MOVOU 96(DX), X10 // X10 = m[12]+m[13] - LONG $0x6c0f4566; BYTE $0xd4 // PUNPCKLQDQ XMM10, XMM12 /* m[12], m[10] */ - MOVOU X12, X11 - LONG $0x6d0f4566; BYTE $0xdd // PUNPCKHQDQ XMM11, XMM13 /* m[11], m[3] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 48(DX), X14 // X14 = m[6]+ m[7] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X14, X9 - LONG $0x6d0f4566; BYTE $0xce // PUNPCKHQDQ XMM9, XMM14 /* ___, m[7] */ - MOVOU X13, X8 - LONG $0x6c0f4566; BYTE $0xc1 // PUNPCKLQDQ XMM8, XMM9 /* m[4], ____ */ - MOVOU X15, X9 - LONG $0x6d0f4566; BYTE $0xcc // PUNPCKHQDQ XMM9, XMM12 /* m[15], m[1] */ - MOVOU 64(DX), X12 // X12 = m[8]+ m[9] - MOVOU 96(DX), X10 // X10 = m[12]+m[13] - LONG $0x6d0f4566; BYTE $0xd5 // PUNPCKHQDQ XMM10, XMM13 /* m[13], m[5] */ - LONG $0x6d0f4566; BYTE $0xe4 // PUNPCKHQDQ XMM12, XMM12 /* ___, m[9] */ - MOVOU X15, X11 - LONG $0x6c0f4566; BYTE $0xdc // PUNPCKLQDQ XMM11, XMM12 /* m[14], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 7 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X12, X9 - LONG $0x6d0f4566; BYTE $0xcc // PUNPCKHQDQ XMM9, XMM12 /* ___, m[1] */ - MOVOU X14, X8 - LONG $0x6c0f4566; BYTE $0xc1 // PUNPCKLQDQ XMM8, XMM9 /* m[12], ____ */ - MOVOU X15, X9 - LONG $0x6c0f4566; BYTE $0xcd // PUNPCKLQDQ XMM9, XMM13 /* m[14], m[4] */ - MOVOU 80(DX), X11 // X11 = m[10]+m[11] - MOVOU X13, X10 - LONG $0x6d0f4566; BYTE $0xd7 // PUNPCKHQDQ XMM10, XMM15 /* m[5], m[15] */ - LONG $0x3a0f4566; WORD $0xde0f; BYTE $0x08 // PALIGNR XMM11, XMM14, 0x8 /* m[13], m[10] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[0], m[6] */ - MOVOU X14, X9 - LONG $0x3a0f4566; WORD $0xce0f; BYTE $0x08 // PALIGNR XMM9, XMM14, 0x8 /* m[9], m[8] */ - MOVOU 16(DX), X11 // X14 = m[2]+ m[3] - MOVOU X13, X10 - LONG $0x6d0f4566; BYTE $0xd3 // PUNPCKHQDQ XMM10, XMM11 /* m[7], m[3] */ - LONG $0x6d0f4566; BYTE $0xff // PUNPCKHQDQ XMM15, XMM15 /* ___, m[11] */ - LONG $0x6c0f4566; BYTE $0xdf // PUNPCKLQDQ XMM11, XMM15 /* m[2], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 8 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X14, X8 - LONG $0x6d0f4566; BYTE $0xc5 // PUNPCKHQDQ XMM8, XMM13 /* m[13], m[7] */ - MOVOU X12, X10 - LONG $0x6d0f4566; BYTE $0xd4 // PUNPCKHQDQ XMM10, XMM12 /* ___, m[3] */ - MOVOU X14, X9 - LONG $0x6c0f4566; BYTE $0xca // PUNPCKLQDQ XMM9, XMM10 /* m[12], ____ */ - MOVOU 0(DX), X11 // X11 = m[0]+ m[1] - MOVOU 64(DX), X13 // X13 = m[8]+ m[9] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU X15, X10 - LONG $0x3a0f4566; WORD $0xd60f; BYTE $0x08 // PALIGNR XMM10, XMM14, 0x8 /* m[11], m[14] */ - LONG $0x6d0f4566; BYTE $0xdd // PUNPCKHQDQ XMM11, XMM13 /* m[1], m[9] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X13, X8 - LONG $0x6d0f4566; BYTE $0xc7 // PUNPCKHQDQ XMM8, XMM15 /* m[5], m[15] */ - MOVOU X14, X9 - LONG $0x6c0f4566; BYTE $0xcc // PUNPCKLQDQ XMM9, XMM12 /* m[8], m[2] */ - MOVOU 0(DX), X10 // X10 = m[0]+ m[1] - MOVOU 48(DX), X11 // X11 = m[6]+ m[7] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - LONG $0x6c0f4566; BYTE $0xd5 // PUNPCKLQDQ XMM10, XMM13 /* m[0], m[4] */ - LONG $0x6c0f4566; BYTE $0xdf // PUNPCKLQDQ XMM11, XMM15 /* m[6], m[10] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 9 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X13, X8 - LONG $0x6c0f4566; BYTE $0xc7 // PUNPCKLQDQ XMM8, XMM15 /* m[6], m[14] */ - MOVOU X12, X9 - LONG $0x3a0f4566; WORD $0xce0f; BYTE $0x08 // PALIGNR XMM9, XMM14, 0x8 /* m[11], m[0] */ - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 64(DX), X11 // X11 = m[8]+ m[9] - MOVOU X15, X10 - LONG $0x6d0f4566; BYTE $0xd3 // PUNPCKHQDQ XMM10, XMM11 /* m[15], m[9] */ - LONG $0x3a0f4566; WORD $0xdd0f; BYTE $0x08 // PALIGNR XMM11, XMM13, 0x8 /* m[3], m[8] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 16(DX), X13 // X13 = m[2]+ m[3] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - MOVOU X15, X9 - LONG $0x6d0f4566; BYTE $0xcf // PUNPCKHQDQ XMM9, XMM15 /* ___, m[13] */ - MOVOU X15, X8 - LONG $0x6c0f4566; BYTE $0xc1 // PUNPCKLQDQ XMM8, XMM9 /* m[12], ____ */ - MOVOU X14, X9 - LONG $0x3a0f4566; WORD $0xcc0f; BYTE $0x08 // PALIGNR XMM9, XMM12, 0x8 /* m[1], m[10] */ - MOVOU 32(DX), X12 // X12 = m[4]+ m[5] - MOVOU 48(DX), X15 // X15 = m[6]+ m[7] - MOVOU X15, X11 - LONG $0x6d0f4566; BYTE $0xdf // PUNPCKHQDQ XMM11, XMM15 /* ___, m[7] */ - MOVOU X13, X10 - LONG $0x6c0f4566; BYTE $0xd3 // PUNPCKLQDQ XMM10, XMM11 /* m[2], ____ */ - MOVOU X12, X15 - LONG $0x6d0f4566; BYTE $0xfc // PUNPCKHQDQ XMM15, XMM12 /* ___, m[5] */ - MOVOU X12, X11 - LONG $0x6c0f4566; BYTE $0xdf // PUNPCKLQDQ XMM11, XMM15 /* m[4], ____ */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 0 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 48(DX), X13 // X13 = m[6]+ m[7] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 80(DX), X15 // X15 = m[10]+m[11] - MOVOU X15, X8 - LONG $0x6c0f4566; BYTE $0xc6 // PUNPCKLQDQ XMM8, XMM14 /* m[10], m[8] */ - MOVOU X13, X9 - LONG $0x6d0f4566; BYTE $0xcc // PUNPCKHQDQ XMM9, XMM12 /* m[7], m[1] */ - MOVOU 16(DX), X10 // X10 = m[2]+ m[3] - MOVOU 32(DX), X14 // X14 = m[4]+ m[5] - LONG $0x6c0f4566; BYTE $0xd6 // PUNPCKLQDQ XMM10, XMM14 /* m[2], m[4] */ - MOVOU X14, X15 - LONG $0x6d0f4566; BYTE $0xfe // PUNPCKHQDQ XMM15, XMM14 /* ___, m[5] */ - MOVOU X13, X11 - LONG $0x6c0f4566; BYTE $0xdf // PUNPCKLQDQ XMM11, XMM15 /* m[6], ____ */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 64(DX), X13 // X13 = m[8]+ m[9] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X15, X8 - LONG $0x6d0f4566; BYTE $0xc5 // PUNPCKHQDQ XMM8, XMM13 /* m[15], m[9] */ - MOVOU X12, X9 - LONG $0x6d0f4566; BYTE $0xce // PUNPCKHQDQ XMM9, XMM14 /* m[3], m[13] */ - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU X15, X10 - LONG $0x3a0f4566; WORD $0xd50f; BYTE $0x08 // PALIGNR XMM10, XMM13, 0x8 /* m[11], m[14] */ - MOVOU X14, X11 - LONG $0x6c0f4566; BYTE $0xdc // PUNPCKLQDQ XMM11, XMM12 /* m[12], m[0] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 1 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+m[1] - MOVOU 16(DX), X13 // X13 = m[2]+m[3] - MOVOU 32(DX), X14 // X14 = m[4]+m[5] - MOVOU 48(DX), X15 // X15 = m[6]+m[7] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[0], m[2] */ - MOVOU X14, X9 - LONG $0x6c0f4566; BYTE $0xcf // PUNPCKLQDQ XMM9, XMM15 /* m[4], m[6] */ - MOVOU X12, X10 - LONG $0x6d0f4566; BYTE $0xd5 // PUNPCKHQDQ XMM10, XMM13 /* m[1], m[3] */ - MOVOU X14, X11 - LONG $0x6d0f4566; BYTE $0xdf // PUNPCKHQDQ XMM11, XMM15 /* m[5], m[7] */ - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 64(DX), X12 // X12 = m[8]+ m[9] - MOVOU 80(DX), X13 // X13 = m[10]+m[11] - MOVOU 96(DX), X14 // X14 = m[12]+m[13] - MOVOU 112(DX), X15 // X15 = m[14]+m[15] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[8],m[10] */ - MOVOU X14, X9 - LONG $0x6c0f4566; BYTE $0xcf // PUNPCKLQDQ XMM9, XMM15 /* m[12],m[14] */ - MOVOU X12, X10 - LONG $0x6d0f4566; BYTE $0xd5 // PUNPCKHQDQ XMM10, XMM13 /* m[9],m[11] */ - MOVOU X14, X11 - LONG $0x6d0f4566; BYTE $0xdf // PUNPCKHQDQ XMM11, XMM15 /* m[13],m[15] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - /////////////////////////////////////////////////////////////////////////// - // R O U N D 1 2 - /////////////////////////////////////////////////////////////////////////// - - // LOAD_MSG_ ##r ##_1 / ##_2(b0, b1); (X12 is temp register) - MOVOU 112(DX), X12 // X12 = m[14]+m[15] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 64(DX), X14 // X14 = m[8]+ m[9] - MOVOU 96(DX), X15 // X15 = m[12]+m[13] - MOVOU X12, X8 - LONG $0x6c0f4566; BYTE $0xc5 // PUNPCKLQDQ XMM8, XMM13 /* m[14], m[4] */ - MOVOU X14, X9 - LONG $0x6d0f4566; BYTE $0xcf // PUNPCKHQDQ XMM9, XMM15 /* m[9], m[13] */ - MOVOU 80(DX), X10 // X10 = m[10]+m[11] - MOVOU 48(DX), X11 // X11 = m[6]+ m[7] - LONG $0x6c0f4566; BYTE $0xd6 // PUNPCKLQDQ XMM10, XMM14 /* m[10], m[8] */ - LONG $0x3a0f4566; WORD $0xdc0f; BYTE $0x08 // PALIGNR XMM11, XMM12, 0x8 /* m[15], m[6] */; ; ; ; ; - - LOAD_SHUFFLE - G1 - G2 - DIAGONALIZE - - // LOAD_MSG_ ##r ##_3 / ##_4(b0, b1); (X12 is temp register) - MOVOU 0(DX), X12 // X12 = m[0]+ m[1] - MOVOU 32(DX), X13 // X13 = m[4]+ m[5] - MOVOU 80(DX), X14 // X14 = m[10]+m[11] - MOVOU X12, X8 - LONG $0x3a0f4566; WORD $0xc40f; BYTE $0x08 // PALIGNR XMM8, XMM12, 0x8 /* m[1], m[0] */ - MOVOU X14, X9 - LONG $0x6d0f4566; BYTE $0xcd // PUNPCKHQDQ XMM9, XMM13 /* m[11], m[5] */ - MOVOU 16(DX), X12 // X12 = m[2]+ m[3] - MOVOU 48(DX), X11 // X11 = m[6]+ m[7] - MOVOU 96(DX), X10 // X10 = m[12]+m[13] - LONG $0x6c0f4566; BYTE $0xd4 // PUNPCKLQDQ XMM10, XMM12 /* m[12], m[2] */ - LONG $0x6d0f4566; BYTE $0xdc // PUNPCKHQDQ XMM11, XMM12 /* m[7], m[3] */ - - LOAD_SHUFFLE - G1 - G2 - UNDIAGONALIZE - - // Reload digest (most current value store in &out) - MOVQ out+144(FP), SI // SI: &in - MOVOU 0(SI), X12 // X12 = in[0]+in[1] /* row1l = LOAD( &S->h[0] ); */ - MOVOU 16(SI), X13 // X13 = in[2]+in[3] /* row1h = LOAD( &S->h[2] ); */ - MOVOU 32(SI), X14 // X14 = in[4]+in[5] /* row2l = LOAD( &S->h[4] ); */ - MOVOU 48(SI), X15 // X15 = in[6]+in[7] /* row2h = LOAD( &S->h[6] ); */ - - // Final computations and prepare for storing - PXOR X4, X0 // X0 = X0 ^ X4 /* row1l = _mm_xor_si128( row3l, row1l ); */ - PXOR X5, X1 // X1 = X1 ^ X5 /* row1h = _mm_xor_si128( row3h, row1h ); */ - PXOR X12, X0 // X0 = X0 ^ X12 /* STORE( &S->h[0], _mm_xor_si128( LOAD( &S->h[0] ), row1l ) ); */ - PXOR X13, X1 // X1 = X1 ^ X13 /* STORE( &S->h[2], _mm_xor_si128( LOAD( &S->h[2] ), row1h ) ); */ - PXOR X6, X2 // X2 = X2 ^ X6 /* row2l = _mm_xor_si128( row4l, row2l ); */ - PXOR X7, X3 // X3 = X3 ^ X7 /* row2h = _mm_xor_si128( row4h, row2h ); */ - PXOR X14, X2 // X2 = X2 ^ X14 /* STORE( &S->h[4], _mm_xor_si128( LOAD( &S->h[4] ), row2l ) ); */ - PXOR X15, X3 // X3 = X3 ^ X15 /* STORE( &S->h[6], _mm_xor_si128( LOAD( &S->h[6] ), row2h ) ); */ - - // Store digest into &out - MOVQ out+144(FP), SI // SI: &out - MOVOU X0, 0(SI) // out[0]+out[1] = X0 - MOVOU X1, 16(SI) // out[2]+out[3] = X1 - MOVOU X2, 32(SI) // out[4]+out[5] = X2 - MOVOU X3, 48(SI) // out[6]+out[7] = X3 - - // Increment message pointer and check if there's more to do - ADDQ $128, DX // message += 128 - SUBQ $1, R8 - JNZ loop - -complete: - RET diff --git a/vendor/github.com/minio/blake2b-simd/compress_amd64.go b/vendor/github.com/minio/blake2b-simd/compress_amd64.go deleted file mode 100644 index 4fc5e388c..000000000 --- a/vendor/github.com/minio/blake2b-simd/compress_amd64.go +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2016 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 blake2b - -func compress(d *digest, p []uint8) { - // Verifies if AVX2 or AVX is available, use optimized code path. - if avx2 { - compressAVX2(d, p) - } else if avx { - compressAVX(d, p) - } else if ssse3 { - compressSSE(d, p) - } else { - compressGeneric(d, p) - } -} diff --git a/vendor/github.com/minio/blake2b-simd/compress_generic.go b/vendor/github.com/minio/blake2b-simd/compress_generic.go deleted file mode 100644 index e9e16e8b9..000000000 --- a/vendor/github.com/minio/blake2b-simd/compress_generic.go +++ /dev/null @@ -1,1419 +0,0 @@ -// Written in 2012 by Dmitry Chestnykh. -// -// To the extent possible under law, the author have dedicated all copyright -// and related and neighboring rights to this software to the public domain -// worldwide. This software is distributed without any warranty. -// http://creativecommons.org/publicdomain/zero/1.0/ - -package blake2b - -func compressGeneric(d *digest, p []uint8) { - h0, h1, h2, h3, h4, h5, h6, h7 := d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] - - for len(p) >= BlockSize { - // Increment counter. - d.t[0] += BlockSize - if d.t[0] < BlockSize { - d.t[1]++ - } - // Initialize compression function. - v0, v1, v2, v3, v4, v5, v6, v7 := h0, h1, h2, h3, h4, h5, h6, h7 - v8 := iv[0] - v9 := iv[1] - v10 := iv[2] - v11 := iv[3] - v12 := iv[4] ^ d.t[0] - v13 := iv[5] ^ d.t[1] - v14 := iv[6] ^ d.f[0] - v15 := iv[7] ^ d.f[1] - - j := 0 - var m [16]uint64 - for i := range m { - m[i] = uint64(p[j]) | uint64(p[j+1])<<8 | uint64(p[j+2])<<16 | - uint64(p[j+3])<<24 | uint64(p[j+4])<<32 | uint64(p[j+5])<<40 | - uint64(p[j+6])<<48 | uint64(p[j+7])<<56 - j += 8 - } - - // Round 1. - v0 += m[0] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[2] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[4] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[6] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[5] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[7] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[3] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[1] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[8] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[10] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[12] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[14] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[13] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[15] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[11] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[9] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 2. - v0 += m[14] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[4] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[9] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[13] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[15] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[6] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[8] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[10] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[1] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[0] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[11] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[5] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[7] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[3] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[2] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[12] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 3. - v0 += m[11] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[12] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[5] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[15] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[2] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[13] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[0] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[8] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[10] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[3] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[7] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[9] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[1] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[4] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[6] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[14] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 4. - v0 += m[7] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[3] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[13] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[11] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[12] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[14] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[1] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[9] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[2] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[5] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[4] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[15] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[0] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[8] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[10] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[6] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 5. - v0 += m[9] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[5] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[2] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[10] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[4] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[15] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[7] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[0] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[14] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[11] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[6] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[3] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[8] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[13] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[12] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[1] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 6. - v0 += m[2] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[6] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[0] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[8] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[11] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[3] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[10] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[12] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[4] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[7] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[15] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[1] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[14] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[9] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[5] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[13] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 7. - v0 += m[12] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[1] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[14] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[4] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[13] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[10] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[15] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[5] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[0] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[6] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[9] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[8] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[2] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[11] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[3] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[7] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 8. - v0 += m[13] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[7] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[12] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[3] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[1] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[9] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[14] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[11] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[5] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[15] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[8] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[2] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[6] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[10] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[4] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[0] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 9. - v0 += m[6] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[14] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[11] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[0] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[3] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[8] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[9] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[15] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[12] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[13] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[1] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[10] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[4] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[5] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[7] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[2] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 10. - v0 += m[10] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[8] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[7] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[1] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[6] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[5] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[4] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[2] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[15] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[9] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[3] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[13] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[12] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[0] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[14] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[11] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 11. - v0 += m[0] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[2] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[4] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[6] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[5] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[7] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[3] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[1] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[8] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[10] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[12] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[14] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[13] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[15] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[11] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[9] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - // Round 12. - v0 += m[14] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-32) | v12>>32 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-24) | v4>>24 - v1 += m[4] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-32) | v13>>32 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-24) | v5>>24 - v2 += m[9] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-32) | v14>>32 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-24) | v6>>24 - v3 += m[13] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-32) | v15>>32 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-24) | v7>>24 - v2 += m[15] - v2 += v6 - v14 ^= v2 - v14 = v14<<(64-16) | v14>>16 - v10 += v14 - v6 ^= v10 - v6 = v6<<(64-63) | v6>>63 - v3 += m[6] - v3 += v7 - v15 ^= v3 - v15 = v15<<(64-16) | v15>>16 - v11 += v15 - v7 ^= v11 - v7 = v7<<(64-63) | v7>>63 - v1 += m[8] - v1 += v5 - v13 ^= v1 - v13 = v13<<(64-16) | v13>>16 - v9 += v13 - v5 ^= v9 - v5 = v5<<(64-63) | v5>>63 - v0 += m[10] - v0 += v4 - v12 ^= v0 - v12 = v12<<(64-16) | v12>>16 - v8 += v12 - v4 ^= v8 - v4 = v4<<(64-63) | v4>>63 - v0 += m[1] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-32) | v15>>32 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-24) | v5>>24 - v1 += m[0] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-32) | v12>>32 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-24) | v6>>24 - v2 += m[11] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-32) | v13>>32 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-24) | v7>>24 - v3 += m[5] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-32) | v14>>32 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-24) | v4>>24 - v2 += m[7] - v2 += v7 - v13 ^= v2 - v13 = v13<<(64-16) | v13>>16 - v8 += v13 - v7 ^= v8 - v7 = v7<<(64-63) | v7>>63 - v3 += m[3] - v3 += v4 - v14 ^= v3 - v14 = v14<<(64-16) | v14>>16 - v9 += v14 - v4 ^= v9 - v4 = v4<<(64-63) | v4>>63 - v1 += m[2] - v1 += v6 - v12 ^= v1 - v12 = v12<<(64-16) | v12>>16 - v11 += v12 - v6 ^= v11 - v6 = v6<<(64-63) | v6>>63 - v0 += m[12] - v0 += v5 - v15 ^= v0 - v15 = v15<<(64-16) | v15>>16 - v10 += v15 - v5 ^= v10 - v5 = v5<<(64-63) | v5>>63 - - h0 ^= v0 ^ v8 - h1 ^= v1 ^ v9 - h2 ^= v2 ^ v10 - h3 ^= v3 ^ v11 - h4 ^= v4 ^ v12 - h5 ^= v5 ^ v13 - h6 ^= v6 ^ v14 - h7 ^= v7 ^ v15 - - p = p[BlockSize:] - } - d.h[0], d.h[1], d.h[2], d.h[3], d.h[4], d.h[5], d.h[6], d.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 -} diff --git a/vendor/github.com/minio/blake2b-simd/compress_noasm.go b/vendor/github.com/minio/blake2b-simd/compress_noasm.go deleted file mode 100644 index d3c675847..000000000 --- a/vendor/github.com/minio/blake2b-simd/compress_noasm.go +++ /dev/null @@ -1,23 +0,0 @@ -//+build !amd64 noasm appengine - -/* - * Minio Cloud Storage, (C) 2016 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 blake2b - -func compress(d *digest, p []uint8) { - compressGeneric(d, p) -} diff --git a/vendor/github.com/minio/blake2b-simd/cpuid.go b/vendor/github.com/minio/blake2b-simd/cpuid.go deleted file mode 100644 index a9f95508e..000000000 --- a/vendor/github.com/minio/blake2b-simd/cpuid.go +++ /dev/null @@ -1,60 +0,0 @@ -// +build 386,!gccgo amd64,!gccgo - -// Copyright 2016 Frank Wessels -// -// 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 blake2b - -func cpuid(op uint32) (eax, ebx, ecx, edx uint32) -func cpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) -func xgetbv(index uint32) (eax, edx uint32) - -// True when SIMD instructions are available. -var avx2 = haveAVX2() -var avx = haveAVX() -var ssse3 = haveSSSE3() - -// haveAVX returns true when there is AVX support -func haveAVX() bool { - _, _, c, _ := cpuid(1) - - // Check XGETBV, OXSAVE and AVX bits - if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 { - // Check for OS support - eax, _ := xgetbv(0) - return (eax & 0x6) == 0x6 - } - return false -} - -// haveAVX2 returns true when there is AVX2 support -func haveAVX2() bool { - mfi, _, _, _ := cpuid(0) - - // Check AVX2, AVX2 requires OS support, but BMI1/2 don't. - if mfi >= 7 && haveAVX() { - _, ebx, _, _ := cpuidex(7, 0) - return (ebx & 0x00000020) != 0 - } - return false -} - -// haveSSSE3 returns true when there is SSSE3 support -func haveSSSE3() bool { - - _, _, c, _ := cpuid(1) - - return (c & 0x00000200) != 0 -} diff --git a/vendor/github.com/minio/blake2b-simd/cpuid_386.s b/vendor/github.com/minio/blake2b-simd/cpuid_386.s deleted file mode 100644 index fa38814ec..000000000 --- a/vendor/github.com/minio/blake2b-simd/cpuid_386.s +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -// +build 386,!gccgo - -// func cpuid(op uint32) (eax, ebx, ecx, edx uint32) -TEXT ·cpuid(SB), 7, $0 - XORL CX, CX - MOVL op+0(FP), AX - CPUID - MOVL AX, eax+4(FP) - MOVL BX, ebx+8(FP) - MOVL CX, ecx+12(FP) - MOVL DX, edx+16(FP) - RET - -// func cpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) -TEXT ·cpuidex(SB), 7, $0 - MOVL op+0(FP), AX - MOVL op2+4(FP), CX - CPUID - MOVL AX, eax+8(FP) - MOVL BX, ebx+12(FP) - MOVL CX, ecx+16(FP) - MOVL DX, edx+20(FP) - RET - -// func xgetbv(index uint32) (eax, edx uint32) -TEXT ·xgetbv(SB), 7, $0 - MOVL index+0(FP), CX - BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV - MOVL AX, eax+4(FP) - MOVL DX, edx+8(FP) - RET diff --git a/vendor/github.com/minio/blake2b-simd/cpuid_amd64.s b/vendor/github.com/minio/blake2b-simd/cpuid_amd64.s deleted file mode 100644 index fb45a6560..000000000 --- a/vendor/github.com/minio/blake2b-simd/cpuid_amd64.s +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. - -// +build amd64,!gccgo - -// func cpuid(op uint32) (eax, ebx, ecx, edx uint32) -TEXT ·cpuid(SB), 7, $0 - XORQ CX, CX - MOVL op+0(FP), AX - CPUID - MOVL AX, eax+8(FP) - MOVL BX, ebx+12(FP) - MOVL CX, ecx+16(FP) - MOVL DX, edx+20(FP) - RET - - -// func cpuidex(op, op2 uint32) (eax, ebx, ecx, edx uint32) -TEXT ·cpuidex(SB), 7, $0 - MOVL op+0(FP), AX - MOVL op2+4(FP), CX - CPUID - MOVL AX, eax+8(FP) - MOVL BX, ebx+12(FP) - MOVL CX, ecx+16(FP) - MOVL DX, edx+20(FP) - RET - -// func xgetbv(index uint32) (eax, edx uint32) -TEXT ·xgetbv(SB), 7, $0 - MOVL index+0(FP), CX - BYTE $0x0f; BYTE $0x01; BYTE $0xd0 // XGETBV - MOVL AX, eax+8(FP) - MOVL DX, edx+12(FP) - RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go new file mode 100644 index 000000000..fa9e48e31 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -0,0 +1,194 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blake2b implements the BLAKE2b hash algorithm as +// defined in RFC 7693. +package blake2b + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2b in bytes. + BlockSize = 128 + // The hash size of BLAKE2b-512 in bytes. + Size = 64 + // The hash size of BLAKE2b-384 in bytes. + Size384 = 48 + // The hash size of BLAKE2b-256 in bytes. + Size256 = 32 +) + +var ( + useAVX2 bool + useAVX bool + useSSE4 bool +) + +var errKeySize = errors.New("blake2b: invalid key size") + +var iv = [8]uint64{ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +} + +// Sum512 returns the BLAKE2b-512 checksum of the data. +func Sum512(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// Sum384 returns the BLAKE2b-384 checksum of the data. +func Sum384(data []byte) [Size384]byte { + var sum [Size]byte + var sum384 [Size384]byte + checkSum(&sum, Size384, data) + copy(sum384[:], sum[:Size384]) + return sum384 +} + +// Sum256 returns the BLAKE2b-256 checksum of the data. +func Sum256(data []byte) [Size256]byte { + var sum [Size]byte + var sum256 [Size256]byte + checkSum(&sum, Size256, data) + copy(sum256[:], sum[:Size256]) + return sum256 +} + +// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 64 bytes long. +func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 64 bytes long. +func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } + +// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 64 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } + +func newDigest(hashSize int, key []byte) (*digest, error) { + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + h := iv + h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) + var c [2]uint64 + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint64(BlockSize - offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h[:(hashSize+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } +} + +type digest struct { + h [8]uint64 + c [2]uint64 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + if len(p) > 0 { + d.offset += copy(d.block[:], p) + } + + return +} + +func (d *digest) Sum(b []byte) []byte { + var block [BlockSize]byte + copy(block[:], d.block[:d.offset]) + remaining := uint64(BlockSize - d.offset) + + c := d.c + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + h := d.h + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + var sum [Size]byte + for i, v := range h[:(d.size+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } + + return append(b, sum[:d.size]...) +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go new file mode 100644 index 000000000..8c41cf6c7 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go @@ -0,0 +1,43 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7,amd64,!gccgo,!appengine + +package blake2b + +func init() { + useAVX2 = supportsAVX2() + useAVX = supportsAVX() + useSSE4 = supportsSSE4() +} + +//go:noescape +func supportsSSE4() bool + +//go:noescape +func supportsAVX() bool + +//go:noescape +func supportsAVX2() bool + +//go:noescape +func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + if useAVX2 { + hashBlocksAVX2(h, c, flag, blocks) + } else if useAVX { + hashBlocksAVX(h, c, flag, blocks) + } else if useSSE4 { + hashBlocksSSE4(h, c, flag, blocks) + } else { + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s new file mode 100644 index 000000000..784bce6a9 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s @@ -0,0 +1,762 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7,amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 + +#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 +#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 +#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e +#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 +#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 + +#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ + VPADDQ m0, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m1, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y1_Y1; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y3_Y3; \ + VPADDQ m2, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m3, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y3_Y3; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y1_Y1 + +#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E +#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 +#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E +#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 +#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E + +#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n +#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n +#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n +#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n +#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n + +#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 +#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 +#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 +#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 +#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 + +#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 + +#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 +#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 + +// load msg: Y12 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y12, Y12 + +// load msg: Y13 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ + VMOVQ_SI_X13(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X13(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y13, Y13 + +// load msg: Y14 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ + VMOVQ_SI_X14(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X14(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y14, Y14 + +// load msg: Y15 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ + VMOVQ_SI_X15(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X15(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X11(6*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ + LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ + LOAD_MSG_AVX2_Y15(9, 11, 13, 15) + +#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ + LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ + LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ + VMOVQ_SI_X11(11*8); \ + VPSHUFD $0x4E, 0*8(SI), X14; \ + VPINSRQ_1_SI_X11(5*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(12, 2, 7, 3) + +#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ + VMOVQ_SI_X11(5*8); \ + VMOVDQU 11*8(SI), X12; \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + VMOVQ_SI_X13(8*8); \ + VMOVQ_SI_X11(2*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X11(13*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ + LOAD_MSG_AVX2_Y15(14, 6, 1, 4) + +#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ + LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ + LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ + LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ + VMOVQ_SI_X15(6*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X15(10*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ + LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X13(7*8); \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ + LOAD_MSG_AVX2_Y15(1, 12, 8, 13) + +#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ + LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ + LOAD_MSG_AVX2_Y15(13, 5, 14, 9) + +#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ + LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ + LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ + VMOVQ_SI_X14_0; \ + VPSHUFD $0x4E, 8*8(SI), X11; \ + VPINSRQ_1_SI_X14(6*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(7, 3, 2, 11) + +#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ + LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ + LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ + LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ + VMOVQ_SI_X15_0; \ + VMOVQ_SI_X11(6*8); \ + VPINSRQ_1_SI_X15(4*8); \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ + VMOVQ_SI_X12(6*8); \ + VMOVQ_SI_X11(11*8); \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ + VMOVQ_SI_X11(1*8); \ + VMOVDQU 12*8(SI), X14; \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + VMOVQ_SI_X15(2*8); \ + VMOVDQU 4*8(SI), X11; \ + VPINSRQ_1_SI_X15(7*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ + LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ + VMOVQ_SI_X13(2*8); \ + VPSHUFD $0x4E, 5*8(SI), X11; \ + VPINSRQ_1_SI_X13(4*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ + VMOVQ_SI_X15(11*8); \ + VMOVQ_SI_X11(12*8); \ + VPINSRQ_1_SI_X15(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y15, Y15 + +// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, DX + MOVQ SP, R9 + ADDQ $31, R9 + ANDQ $~31, R9 + MOVQ R9, SP + + MOVQ CX, 16(SP) + XORQ CX, CX + MOVQ CX, 24(SP) + + VMOVDQU ·AVX2_c40<>(SB), Y4 + VMOVDQU ·AVX2_c48<>(SB), Y5 + + VMOVDQU 0(AX), Y8 + VMOVDQU 32(AX), Y9 + VMOVDQU ·AVX2_iv0<>(SB), Y6 + VMOVDQU ·AVX2_iv1<>(SB), Y7 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + MOVQ R9, 8(SP) + +loop: + ADDQ $128, R8 + MOVQ R8, 0(SP) + CMPQ R8, $128 + JGE noinc + INCQ R9 + MOVQ R9, 8(SP) + +noinc: + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR 0(SP), Y7, Y3 + + LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() + VMOVDQA Y12, 32(SP) + VMOVDQA Y13, 64(SP) + VMOVDQA Y14, 96(SP) + VMOVDQA Y15, 128(SP) + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() + VMOVDQA Y12, 160(SP) + VMOVDQA Y13, 192(SP) + VMOVDQA Y14, 224(SP) + VMOVDQA Y15, 256(SP) + + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5) + ROUND_AVX2(160(SP), 192(SP), 224(SP), 256(SP), Y10, Y4, Y5) + + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + + VMOVDQU Y8, 0(AX) + VMOVDQU Y9, 32(AX) + VZEROUPPER + + MOVQ DX, SP + RET + +#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA +#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB +#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF +#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD +#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE + +#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF +#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF + +#define SHUFFLE_AVX() \ + VMOVDQA X6, X13; \ + VMOVDQA X2, X14; \ + VMOVDQA X4, X6; \ + VPUNPCKLQDQ_X13_X13_X15; \ + VMOVDQA X5, X4; \ + VMOVDQA X6, X5; \ + VPUNPCKHQDQ_X15_X7_X6; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X13_X7; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VPUNPCKHQDQ_X15_X2_X2; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X3_X3; \ + +#define SHUFFLE_AVX_INV() \ + VMOVDQA X2, X13; \ + VMOVDQA X4, X14; \ + VPUNPCKLQDQ_X2_X2_X15; \ + VMOVDQA X5, X4; \ + VPUNPCKHQDQ_X15_X3_X2; \ + VMOVDQA X14, X5; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VMOVDQA X6, X14; \ + VPUNPCKHQDQ_X15_X13_X3; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X6_X6; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X7_X7; \ + +#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + VPADDQ m0, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m1, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFD $-79, v6, v6; \ + VPSHUFD $-79, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPSHUFB c40, v2, v2; \ + VPSHUFB c40, v3, v3; \ + VPADDQ m2, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m3, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFB c48, v6, v6; \ + VPSHUFB c48, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPADDQ v2, v2, t0; \ + VPSRLQ $63, v2, v2; \ + VPXOR t0, v2, v2; \ + VPADDQ v3, v3, t0; \ + VPSRLQ $63, v3, v3; \ + VPXOR t0, v3, v3 + +// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) +// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 +#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X13(i2*8); \ + VMOVQ_SI_X14(i4*8); \ + VMOVQ_SI_X15(i6*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X13(i3*8); \ + VPINSRQ_1_SI_X14(i5*8); \ + VPINSRQ_1_SI_X15(i7*8) + +// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) +#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(1*8); \ + VMOVQ_SI_X15(5*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X13(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(7*8) + +// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) +#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ + VPSHUFD $0x4E, 0*8(SI), X12; \ + VMOVQ_SI_X13(11*8); \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(7*8); \ + VPINSRQ_1_SI_X13(5*8); \ + VPINSRQ_1_SI_X14(2*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) +#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ + VMOVDQU 11*8(SI), X12; \ + VMOVQ_SI_X13(5*8); \ + VMOVQ_SI_X14(8*8); \ + VMOVQ_SI_X15(2*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14_0; \ + VPINSRQ_1_SI_X15(13*8) + +// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) +#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(6*8); \ + VMOVQ_SI_X15_0; \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) +#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ + VMOVQ_SI_X12(9*8); \ + VMOVQ_SI_X13(2*8); \ + VMOVQ_SI_X14_0; \ + VMOVQ_SI_X15(4*8); \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VPINSRQ_1_SI_X15(15*8) + +// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) +#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(11*8); \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X13(8*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) +#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ + MOVQ 0*8(SI), X12; \ + VPSHUFD $0x4E, 8*8(SI), X13; \ + MOVQ 7*8(SI), X14; \ + MOVQ 2*8(SI), X15; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(11*8) + +// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) +#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ + MOVQ 6*8(SI), X12; \ + MOVQ 11*8(SI), X13; \ + MOVQ 15*8(SI), X14; \ + MOVQ 3*8(SI), X15; \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X14(9*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) +#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ + MOVQ 5*8(SI), X12; \ + MOVQ 8*8(SI), X13; \ + MOVQ 0*8(SI), X14; \ + MOVQ 6*8(SI), X15; \ + VPINSRQ_1_SI_X12(15*8); \ + VPINSRQ_1_SI_X13(2*8); \ + VPINSRQ_1_SI_X14(4*8); \ + VPINSRQ_1_SI_X15(10*8) + +// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) +#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ + VMOVDQU 12*8(SI), X12; \ + MOVQ 1*8(SI), X13; \ + MOVQ 2*8(SI), X14; \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VMOVDQU 4*8(SI), X15 + +// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) +#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ + MOVQ 15*8(SI), X12; \ + MOVQ 3*8(SI), X13; \ + MOVQ 11*8(SI), X14; \ + MOVQ 12*8(SI), X15; \ + VPINSRQ_1_SI_X12(9*8); \ + VPINSRQ_1_SI_X13(13*8); \ + VPINSRQ_1_SI_X14(14*8); \ + VPINSRQ_1_SI_X15_0 + +// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, BP + MOVQ SP, R9 + ADDQ $15, R9 + ANDQ $~15, R9 + MOVQ R9, SP + + VMOVDQU ·AVX_c40<>(SB), X0 + VMOVDQU ·AVX_c48<>(SB), X1 + VMOVDQA X0, X8 + VMOVDQA X1, X9 + + VMOVDQU ·AVX_iv3<>(SB), X0 + VMOVDQA X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0) + + VMOVDQU 0(AX), X10 + VMOVDQU 16(AX), X11 + VMOVDQU 32(AX), X2 + VMOVDQU 48(AX), X3 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $128, R8 + CMPQ R8, $128 + JGE noinc + INCQ R9 + +noinc: + VMOVQ_R8_X15 + VPINSRQ_1_R9_X15 + + VMOVDQA X10, X0 + VMOVDQA X11, X1 + VMOVDQU ·AVX_iv0<>(SB), X4 + VMOVDQU ·AVX_iv1<>(SB), X5 + VMOVDQU ·AVX_iv2<>(SB), X6 + + VPXOR X15, X6, X6 + VMOVDQA 0(SP), X7 + + LOAD_MSG_AVX_0_2_4_6_1_3_5_7() + VMOVDQA X12, 16(SP) + VMOVDQA X13, 32(SP) + VMOVDQA X14, 48(SP) + VMOVDQA X15, 64(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) + VMOVDQA X12, 80(SP) + VMOVDQA X13, 96(SP) + VMOVDQA X14, 112(SP) + VMOVDQA X15, 128(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) + VMOVDQA X12, 144(SP) + VMOVDQA X13, 160(SP) + VMOVDQA X14, 176(SP) + VMOVDQA X15, 192(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_1_0_11_5_12_2_7_3() + VMOVDQA X12, 208(SP) + VMOVDQA X13, 224(SP) + VMOVDQA X14, 240(SP) + VMOVDQA X15, 256(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_11_12_5_15_8_0_2_13() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_2_5_4_15_6_10_0_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_9_5_2_10_0_7_4_15() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_2_6_0_8_12_10_11_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_0_6_9_8_7_3_2_11() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_5_15_8_2_0_4_6_10() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_6_14_11_0_15_9_3_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_12_13_1_10_2_7_4_5() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_15_9_3_13_11_14_12_0() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9) + SHUFFLE_AVX_INV() + + VMOVDQU 32(AX), X14 + VMOVDQU 48(AX), X15 + VPXOR X0, X10, X10 + VPXOR X1, X11, X11 + VPXOR X2, X14, X14 + VPXOR X3, X15, X15 + VPXOR X4, X10, X10 + VPXOR X5, X11, X11 + VPXOR X6, X14, X2 + VPXOR X7, X15, X3 + VMOVDQU X2, 32(AX) + VMOVDQU X3, 48(AX) + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + VMOVDQU X10, 0(AX) + VMOVDQU X11, 16(AX) + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + VZEROUPPER + + MOVQ BP, SP + RET + +// func supportsAVX2() bool +TEXT ·supportsAVX2(SB), 4, $0-1 + MOVQ runtime·support_avx2(SB), AX + MOVB AX, ret+0(FP) + RET + +// func supportsAVX() bool +TEXT ·supportsAVX(SB), 4, $0-1 + MOVQ runtime·support_avx(SB), AX + MOVB AX, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go new file mode 100644 index 000000000..2ab7c30fc --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go @@ -0,0 +1,25 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7,amd64,!gccgo,!appengine + +package blake2b + +func init() { + useSSE4 = supportsSSE4() +} + +//go:noescape +func supportsSSE4() bool + +//go:noescape +func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + if useSSE4 { + hashBlocksSSE4(h, c, flag, blocks) + } else { + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s new file mode 100644 index 000000000..64530740b --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s @@ -0,0 +1,290 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 + +#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v6, t1; \ + PUNPCKLQDQ v6, t2; \ + PUNPCKHQDQ v7, v6; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ v7, t2; \ + MOVO t1, v7; \ + MOVO v2, t1; \ + PUNPCKHQDQ t2, v7; \ + PUNPCKLQDQ v3, t2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v3 + +#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v2, t1; \ + PUNPCKLQDQ v2, t2; \ + PUNPCKHQDQ v3, v2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ v3, t2; \ + MOVO t1, v3; \ + MOVO v6, t1; \ + PUNPCKHQDQ t2, v3; \ + PUNPCKLQDQ v7, t2; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v7 + +#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + PADDQ m0, v0; \ + PADDQ m1, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFD $0xB1, v6, v6; \ + PSHUFD $0xB1, v7, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + PSHUFB c40, v2; \ + PSHUFB c40, v3; \ + PADDQ m2, v0; \ + PADDQ m3, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFB c48, v6; \ + PSHUFB c48, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + MOVOU v2, t0; \ + PADDQ v2, t0; \ + PSRLQ $63, v2; \ + PXOR t0, v2; \ + MOVOU v3, t0; \ + PADDQ v3, t0; \ + PSRLQ $63, v3; \ + PXOR t0, v3 + +#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ + MOVQ i0*8(src), m0; \ + PINSRQ $1, i1*8(src), m0; \ + MOVQ i2*8(src), m1; \ + PINSRQ $1, i3*8(src), m1; \ + MOVQ i4*8(src), m2; \ + PINSRQ $1, i5*8(src), m2; \ + MOVQ i6*8(src), m3; \ + PINSRQ $1, i7*8(src), m3 + +// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, BP + MOVQ SP, R9 + ADDQ $15, R9 + ANDQ $~15, R9 + MOVQ R9, SP + + MOVOU ·iv3<>(SB), X0 + MOVO X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0) + + MOVOU ·c40<>(SB), X13 + MOVOU ·c48<>(SB), X14 + + MOVOU 0(AX), X12 + MOVOU 16(AX), X15 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $128, R8 + CMPQ R8, $128 + JGE noinc + INCQ R9 + +noinc: + MOVQ R8, X8 + PINSRQ $1, R9, X8 + + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>(SB), X4 + MOVOU ·iv1<>(SB), X5 + MOVOU ·iv2<>(SB), X6 + + PXOR X8, X6 + MOVO 0(SP), X7 + + LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) + MOVO X8, 16(SP) + MOVO X9, 32(SP) + MOVO X10, 48(SP) + MOVO X11, 64(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) + MOVO X8, 80(SP) + MOVO X9, 96(SP) + MOVO X10, 112(SP) + MOVO X11, 128(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) + MOVO X8, 144(SP) + MOVO X9, 160(SP) + MOVO X10, 176(SP) + MOVO X11, 192(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) + MOVO X8, 208(SP) + MOVO X9, 224(SP) + MOVO X10, 240(SP) + MOVO X11, 256(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + MOVOU X12, 0(AX) + MOVOU X15, 16(AX) + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + + MOVQ BP, SP + RET + +// func supportsSSE4() bool +TEXT ·supportsSSE4(SB), 4, $0-1 + MOVL $1, AX + CPUID + SHRL $19, CX // Bit 19 indicates SSE4 support + ANDL $1, CX // CX != 0 if support SSE4 + MOVB CX, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go new file mode 100644 index 000000000..4bd2abc91 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go @@ -0,0 +1,179 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import "encoding/binary" + +// the precomputed values for BLAKE2b +// there are 12 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [12][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second +} + +func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + + for j := range precomputed { + s := &(precomputed[j]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = v12<<(64-32) | v12>>32 + v8 += v12 + v4 ^= v8 + v4 = v4<<(64-24) | v4>>24 + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = v13<<(64-32) | v13>>32 + v9 += v13 + v5 ^= v9 + v5 = v5<<(64-24) | v5>>24 + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = v14<<(64-32) | v14>>32 + v10 += v14 + v6 ^= v10 + v6 = v6<<(64-24) | v6>>24 + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = v15<<(64-32) | v15>>32 + v11 += v15 + v7 ^= v11 + v7 = v7<<(64-24) | v7>>24 + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = v12<<(64-16) | v12>>16 + v8 += v12 + v4 ^= v8 + v4 = v4<<(64-63) | v4>>63 + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = v13<<(64-16) | v13>>16 + v9 += v13 + v5 ^= v9 + v5 = v5<<(64-63) | v5>>63 + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = v14<<(64-16) | v14>>16 + v10 += v14 + v6 ^= v10 + v6 = v6<<(64-63) | v6>>63 + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = v15<<(64-16) | v15>>16 + v11 += v15 + v7 ^= v11 + v7 = v7<<(64-63) | v7>>63 + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = v15<<(64-32) | v15>>32 + v10 += v15 + v5 ^= v10 + v5 = v5<<(64-24) | v5>>24 + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = v12<<(64-32) | v12>>32 + v11 += v12 + v6 ^= v11 + v6 = v6<<(64-24) | v6>>24 + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = v13<<(64-32) | v13>>32 + v8 += v13 + v7 ^= v8 + v7 = v7<<(64-24) | v7>>24 + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = v14<<(64-32) | v14>>32 + v9 += v14 + v4 ^= v9 + v4 = v4<<(64-24) | v4>>24 + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = v15<<(64-16) | v15>>16 + v10 += v15 + v5 ^= v10 + v5 = v5<<(64-63) | v5>>63 + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = v12<<(64-16) | v12>>16 + v11 += v12 + v6 ^= v11 + v6 = v6<<(64-63) | v6>>63 + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = v13<<(64-16) | v13>>16 + v8 += v13 + v7 ^= v8 + v7 = v7<<(64-63) | v7>>63 + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = v14<<(64-16) | v14>>16 + v9 += v14 + v4 ^= v9 + v4 = v4<<(64-63) | v4>>63 + + } + + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 + } + c[0], c[1] = c0, c1 +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go new file mode 100644 index 000000000..da156a1ba --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go @@ -0,0 +1,11 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine gccgo + +package blake2b + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + hashBlocksGeneric(h, c, flag, blocks) +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_test.go b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go new file mode 100644 index 000000000..a38fceb20 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go @@ -0,0 +1,448 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package blake2b + +import ( + "bytes" + "encoding/hex" + "fmt" + "hash" + "testing" +) + +func fromHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func TestHashes(t *testing.T) { + defer func(sse4, avx, avx2 bool) { + useSSE4, useAVX, useAVX2 = sse4, useAVX, avx2 + }(useSSE4, useAVX, useAVX2) + + if useAVX2 { + t.Log("AVX2 version") + testHashes(t) + useAVX2 = false + } + if useAVX { + t.Log("AVX version") + testHashes(t) + useAVX = false + } + if useSSE4 { + t.Log("SSE4 version") + testHashes(t) + useSSE4 = false + } + t.Log("generic version") + testHashes(t) +} + +func testHashes(t *testing.T) { + key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") + + input := make([]byte, 255) + for i := range input { + input[i] = byte(i) + } + + for i, expectedHex := range hashes { + h, err := New512(key) + if err != nil { + t.Fatalf("#%d: error from New512: %v", i, err) + } + + h.Write(input[:i]) + sum := h.Sum(nil) + + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) + } + + h.Reset() + for j := 0; j < i; j++ { + h.Write(input[j : j+1]) + } + + sum = h.Sum(sum[:0]) + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) + } + } +} + +func generateSequence(out []byte, seed uint32) { + a := 0xDEAD4BAD * seed // prime + b := uint32(1) + + for i := range out { // fill the buf + a, b = b, a+b + out[i] = byte(b >> 24) + } +} + +func computeMAC(msg []byte, hashSize int, key []byte) (sum []byte) { + var h hash.Hash + switch hashSize { + case Size: + h, _ = New512(key) + case Size384: + h, _ = New384(key) + case Size256: + h, _ = New256(key) + case 20: + h, _ = newDigest(20, key) + default: + panic("unexpected hashSize") + } + + h.Write(msg) + return h.Sum(sum) +} + +func computeHash(msg []byte, hashSize int) (sum []byte) { + switch hashSize { + case Size: + hash := Sum512(msg) + return hash[:] + case Size384: + hash := Sum384(msg) + return hash[:] + case Size256: + hash := Sum256(msg) + return hash[:] + case 20: + var hash [64]byte + checkSum(&hash, 20, msg) + return hash[:20] + default: + panic("unexpected hashSize") + } +} + +// Test function from RFC 7693. +func TestSelfTest(t *testing.T) { + hashLens := [4]int{20, 32, 48, 64} + msgLens := [6]int{0, 3, 128, 129, 255, 1024} + + msg := make([]byte, 1024) + key := make([]byte, 64) + + h, _ := New256(nil) + for _, hashSize := range hashLens { + for _, msgLength := range msgLens { + generateSequence(msg[:msgLength], uint32(msgLength)) // unkeyed hash + + md := computeHash(msg[:msgLength], hashSize) + h.Write(md) + + generateSequence(key[:], uint32(hashSize)) // keyed hash + md = computeMAC(msg[:msgLength], hashSize, key[:hashSize]) + h.Write(md) + } + } + + sum := h.Sum(nil) + expected := [32]byte{ + 0xc2, 0x3a, 0x78, 0x00, 0xd9, 0x81, 0x23, 0xbd, + 0x10, 0xf5, 0x06, 0xc6, 0x1e, 0x29, 0xda, 0x56, + 0x03, 0xd7, 0x63, 0xb8, 0xbb, 0xad, 0x2e, 0x73, + 0x7f, 0x5e, 0x76, 0x5a, 0x7b, 0xcc, 0xd4, 0x75, + } + if !bytes.Equal(sum, expected[:]) { + t.Fatalf("got %x, wanted %x", sum, expected) + } +} + +// Benchmarks + +func benchmarkSum(b *testing.B, size int) { + data := make([]byte, size) + b.SetBytes(int64(size)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sum512(data) + } +} + +func benchmarkWrite(b *testing.B, size int) { + data := make([]byte, size) + h, _ := New512(nil) + b.SetBytes(int64(size)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + h.Write(data) + } +} + +func BenchmarkWrite128(b *testing.B) { benchmarkWrite(b, 128) } +func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } + +func BenchmarkSum128(b *testing.B) { benchmarkSum(b, 128) } +func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } + +// These values were taken from https://blake2.net/blake2b-test.txt. +var hashes = []string{ + "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568", + "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd", + "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965", + "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1", + "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac", + "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb", + "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f", + "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52", + "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9", + "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637", + "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd", + "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b", + "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563", + "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355", + "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6", + "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e", + "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93", + "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1", + "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670", + "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9", + "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c", + "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd", + "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152", + "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9", + "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f", + "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b", + "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764", + "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d", + "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55", + "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b", + "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e", + "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7", + "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991", + "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347", + "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82", + "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42", + "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327", + "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760", + "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252", + "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55", + "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1", + "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee", + "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa", + "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7", + "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071", + "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4", + "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf", + "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d", + "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8", + "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487", + "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c", + "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2", + "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa", + "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33", + "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d", + "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e", + "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2", + "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4", + "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2", + "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a", + "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564", + "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f", + "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9", + "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa", + "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022", + "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c", + "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc", + "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f", + "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b", + "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866", + "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d", + "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8", + "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4", + "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3", + "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e", + "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745", + "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545", + "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063", + "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd", + "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a", + "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed", + "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd", + "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275", + "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897", + "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430", + "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab", + "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f", + "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46", + "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29", + "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab", + "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8", + "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a", + "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec", + "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79", + "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24", + "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b", + "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5", + "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463", + "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4", + "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3", + "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9", + "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d", + "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4", + "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a", + "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6", + "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73", + "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6", + "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6", + "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3", + "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa", + "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3", + "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b", + "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f", + "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc", + "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200", + "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6", + "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8", + "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f", + "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a", + "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e", + "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935", + "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74", + "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0", + "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c", + "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145", + "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f", + "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0", + "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb", + "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4", + "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91", + "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89", + "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444", + "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a", + "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414", + "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49", + "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b", + "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0", + "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469", + "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3", + "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd", + "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8", + "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21", + "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989", + "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1", + "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399", + "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0", + "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723", + "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff", + "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc", + "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38", + "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a", + "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051", + "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca", + "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4", + "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677", + "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1", + "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce", + "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347", + "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91", + "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209", + "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659", + "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381", + "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56", + "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7", + "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f", + "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972", + "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe", + "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e", + "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be", + "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8", + "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc", + "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8", + "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0", + "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc", + "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979", + "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29", + "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d", + "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108", + "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45", + "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4", + "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267", + "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d", + "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb", + "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813", + "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc", + "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29", + "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc", + "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16", + "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1", + "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c", + "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7", + "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a", + "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa", + "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e", + "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc", + "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5", + "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a", + "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3", + "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc", + "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d", + "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff", + "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb", + "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4", + "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc", + "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902", + "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e", + "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08", + "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816", + "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406", + "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4", + "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d", + "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d", + "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900", + "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06", + "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01", + "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0", + "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94", + "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02", + "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492", + "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2", + "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c", + "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb", + "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077", + "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727", + "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd", + "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c", + "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0", + "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403", + "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391", + "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8", + "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605", + "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9", + "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d", + "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe", + "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe", + "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1", + "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3", + "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb", + "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b", + "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef", + "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253", + "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec", + "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a", + "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473", + "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837", + "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a", + "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1", + "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d", + "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9", + "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537", + "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7", + "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2", + "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338", + "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15", + "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9", + "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461", +} From 1b4bb94ac4fd328e49af2d5e0fe23c912335ed9b Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 9 Feb 2017 15:20:54 -0800 Subject: [PATCH 58/75] config: setter/getter for Notifier and Logger into its own struct. (#3721) This is an attempt cleanup code and keep the top level config functions simpler and easy to understand where as move the notifier related code and logger setter/getter methods as part of their own struct. Locks are now held properly not globally by configMutex, but instead as private variables. Final fix for #3700 --- cmd/bucket-notification-utils.go | 14 +- cmd/config-migrate.go | 5 +- cmd/config-v13.go | 196 +------------------------- cmd/config-v13_test.go | 28 ++-- cmd/event-notifier.go | 14 +- cmd/event-notifier_test.go | 12 +- cmd/logger-console-hook.go | 2 +- cmd/logger-file-hook.go | 2 +- cmd/logger.go | 30 ++++ cmd/notifier-config.go | 228 +++++++++++++++++++++++++++++++ cmd/notifier-config_test.go | 17 +++ cmd/notifiers.go | 26 +--- cmd/notify-amqp.go | 2 +- cmd/notify-elasticsearch.go | 2 +- cmd/notify-kafka.go | 2 +- cmd/notify-nats.go | 2 +- cmd/notify-postgresql.go | 2 +- cmd/notify-redis.go | 2 +- cmd/notify-webhook.go | 2 +- cmd/notify-webhook_test.go | 6 +- 20 files changed, 338 insertions(+), 256 deletions(-) create mode 100644 cmd/notifier-config.go create mode 100644 cmd/notifier-config_test.go diff --git a/cmd/bucket-notification-utils.go b/cmd/bucket-notification-utils.go index 2c0e735f5..8845c5cdb 100644 --- a/cmd/bucket-notification-utils.go +++ b/cmd/bucket-notification-utils.go @@ -133,27 +133,27 @@ func isValidQueueID(queueARN string) bool { // Is Queue identifier valid?. if isAMQPQueue(sqsARN) { // AMQP eueue. - amqpN := serverConfig.GetAMQPNotifyByID(sqsARN.AccountID) + amqpN := serverConfig.Notify.GetAMQPByID(sqsARN.AccountID) return amqpN.Enable && amqpN.URL != "" } else if isNATSQueue(sqsARN) { - natsN := serverConfig.GetNATSNotifyByID(sqsARN.AccountID) + natsN := serverConfig.Notify.GetNATSByID(sqsARN.AccountID) return natsN.Enable && natsN.Address != "" } else if isElasticQueue(sqsARN) { // Elastic queue. - elasticN := serverConfig.GetElasticSearchNotifyByID(sqsARN.AccountID) + elasticN := serverConfig.Notify.GetElasticSearchByID(sqsARN.AccountID) return elasticN.Enable && elasticN.URL != "" } else if isRedisQueue(sqsARN) { // Redis queue. - redisN := serverConfig.GetRedisNotifyByID(sqsARN.AccountID) + redisN := serverConfig.Notify.GetRedisByID(sqsARN.AccountID) return redisN.Enable && redisN.Addr != "" } else if isPostgreSQLQueue(sqsARN) { - pgN := serverConfig.GetPostgreSQLNotifyByID(sqsARN.AccountID) + pgN := serverConfig.Notify.GetPostgreSQLByID(sqsARN.AccountID) // Postgres can work with only default conn. info. return pgN.Enable } else if isKafkaQueue(sqsARN) { - kafkaN := serverConfig.GetKafkaNotifyByID(sqsARN.AccountID) + kafkaN := serverConfig.Notify.GetKafkaByID(sqsARN.AccountID) return (kafkaN.Enable && len(kafkaN.Brokers) > 0 && kafkaN.Topic != "") } else if isWebhookQueue(sqsARN) { - webhookN := serverConfig.GetWebhookNotifyByID(sqsARN.AccountID) + webhookN := serverConfig.Notify.GetWebhookByID(sqsARN.AccountID) return webhookN.Enable && webhookN.Endpoint != "" } return false diff --git a/cmd/config-migrate.go b/cmd/config-migrate.go index f153f17ff..d6a07b045 100644 --- a/cmd/config-migrate.go +++ b/cmd/config-migrate.go @@ -855,7 +855,10 @@ func migrateV12ToV13() error { } // Copy over fields from V12 into V13 config struct - srvConfig := &serverConfigV13{} + srvConfig := &serverConfigV13{ + Logger: &logger{}, + Notify: ¬ifier{}, + } srvConfig.Version = "13" srvConfig.Credential = cv12.Credential srvConfig.Region = cv12.Region diff --git a/cmd/config-v13.go b/cmd/config-v13.go index 8e66c5f70..f1ee32b90 100644 --- a/cmd/config-v13.go +++ b/cmd/config-v13.go @@ -36,10 +36,10 @@ type serverConfigV13 struct { Region string `json:"region"` // Additional error logging configuration. - Logger logger `json:"logger"` + Logger *logger `json:"logger"` // Notification queue configuration. - Notify notifier `json:"notify"` + Notify *notifier `json:"notify"` } // newConfig - initialize a new server config, saves creds from env @@ -47,7 +47,10 @@ type serverConfigV13 struct { // and those are saved. func newConfig(envCreds credential) error { // Initialize server config. - srvCfg := &serverConfigV13{} + srvCfg := &serverConfigV13{ + Logger: &logger{}, + Notify: ¬ifier{}, + } srvCfg.Version = globalMinioConfigVersion srvCfg.Region = globalMinioDefaultRegion @@ -148,193 +151,6 @@ func (s serverConfigV13) GetVersion() string { return s.Version } -/// Logger related. - -func (s *serverConfigV13) SetAMQPNotifyByID(accountID string, amqpn amqpNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.AMQP[accountID] = amqpn -} - -func (s serverConfigV13) GetAMQP() map[string]amqpNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.AMQP -} - -// GetAMQPNotify get current AMQP logger. -func (s serverConfigV13) GetAMQPNotifyByID(accountID string) amqpNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.AMQP[accountID] -} - -// -func (s *serverConfigV13) SetNATSNotifyByID(accountID string, natsn natsNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.NATS[accountID] = natsn -} - -func (s serverConfigV13) GetNATS() map[string]natsNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - return s.Notify.NATS -} - -// GetNATSNotify get current NATS logger. -func (s serverConfigV13) GetNATSNotifyByID(accountID string) natsNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.NATS[accountID] -} - -func (s *serverConfigV13) SetElasticSearchNotifyByID(accountID string, esNotify elasticSearchNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.ElasticSearch[accountID] = esNotify -} - -func (s serverConfigV13) GetElasticSearch() map[string]elasticSearchNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.ElasticSearch -} - -// GetElasticSearchNotify get current ElasicSearch logger. -func (s serverConfigV13) GetElasticSearchNotifyByID(accountID string) elasticSearchNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.ElasticSearch[accountID] -} - -func (s *serverConfigV13) SetRedisNotifyByID(accountID string, rNotify redisNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.Redis[accountID] = rNotify -} - -func (s serverConfigV13) GetRedis() map[string]redisNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.Redis -} - -func (s serverConfigV13) GetWebhook() map[string]webhookNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.Webhook -} - -// GetWebhookNotifyByID get current Webhook logger. -func (s serverConfigV13) GetWebhookNotifyByID(accountID string) webhookNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.Webhook[accountID] -} - -func (s *serverConfigV13) SetWebhookNotifyByID(accountID string, pgn webhookNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.Webhook[accountID] = pgn -} - -// GetRedisNotify get current Redis logger. -func (s serverConfigV13) GetRedisNotifyByID(accountID string) redisNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.Redis[accountID] -} - -func (s *serverConfigV13) SetPostgreSQLNotifyByID(accountID string, pgn postgreSQLNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.PostgreSQL[accountID] = pgn -} - -func (s serverConfigV13) GetPostgreSQL() map[string]postgreSQLNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.PostgreSQL -} - -func (s serverConfigV13) GetPostgreSQLNotifyByID(accountID string) postgreSQLNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.PostgreSQL[accountID] -} - -// Kafka related functions -func (s *serverConfigV13) SetKafkaNotifyByID(accountID string, kn kafkaNotify) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Notify.Kafka[accountID] = kn -} - -func (s serverConfigV13) GetKafka() map[string]kafkaNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.Kafka -} - -func (s serverConfigV13) GetKafkaNotifyByID(accountID string) kafkaNotify { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Notify.Kafka[accountID] -} - -// SetFileLogger set new file logger. -func (s *serverConfigV13) SetFileLogger(flogger fileLogger) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Logger.File = flogger -} - -// GetFileLogger get current file logger. -func (s serverConfigV13) GetFileLogger() fileLogger { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Logger.File -} - -// SetConsoleLogger set new console logger. -func (s *serverConfigV13) SetConsoleLogger(clogger consoleLogger) { - serverConfigMu.Lock() - defer serverConfigMu.Unlock() - - s.Logger.Console = clogger -} - -// GetConsoleLogger get current console logger. -func (s serverConfigV13) GetConsoleLogger() consoleLogger { - serverConfigMu.RLock() - defer serverConfigMu.RUnlock() - - return s.Logger.Console -} - // SetRegion set new region. func (s *serverConfigV13) SetRegion(region string) { serverConfigMu.Lock() diff --git a/cmd/config-v13_test.go b/cmd/config-v13_test.go index b620b00ff..bd505c743 100644 --- a/cmd/config-v13_test.go +++ b/cmd/config-v13_test.go @@ -40,54 +40,54 @@ func TestServerConfig(t *testing.T) { } // Set new amqp notification id. - serverConfig.SetAMQPNotifyByID("2", amqpNotify{}) - savedNotifyCfg1 := serverConfig.GetAMQPNotifyByID("2") + serverConfig.Notify.SetAMQPByID("2", amqpNotify{}) + savedNotifyCfg1 := serverConfig.Notify.GetAMQPByID("2") if !reflect.DeepEqual(savedNotifyCfg1, amqpNotify{}) { t.Errorf("Expecting AMQP config %#v found %#v", amqpNotify{}, savedNotifyCfg1) } // Set new elastic search notification id. - serverConfig.SetElasticSearchNotifyByID("2", elasticSearchNotify{}) - savedNotifyCfg2 := serverConfig.GetElasticSearchNotifyByID("2") + serverConfig.Notify.SetElasticSearchByID("2", elasticSearchNotify{}) + savedNotifyCfg2 := serverConfig.Notify.GetElasticSearchByID("2") if !reflect.DeepEqual(savedNotifyCfg2, elasticSearchNotify{}) { t.Errorf("Expecting Elasticsearch config %#v found %#v", elasticSearchNotify{}, savedNotifyCfg2) } // Set new redis notification id. - serverConfig.SetRedisNotifyByID("2", redisNotify{}) - savedNotifyCfg3 := serverConfig.GetRedisNotifyByID("2") + serverConfig.Notify.SetRedisByID("2", redisNotify{}) + savedNotifyCfg3 := serverConfig.Notify.GetRedisByID("2") if !reflect.DeepEqual(savedNotifyCfg3, redisNotify{}) { t.Errorf("Expecting Redis config %#v found %#v", redisNotify{}, savedNotifyCfg3) } // Set new kafka notification id. - serverConfig.SetKafkaNotifyByID("2", kafkaNotify{}) - savedNotifyCfg4 := serverConfig.GetKafkaNotifyByID("2") + serverConfig.Notify.SetKafkaByID("2", kafkaNotify{}) + savedNotifyCfg4 := serverConfig.Notify.GetKafkaByID("2") if !reflect.DeepEqual(savedNotifyCfg4, kafkaNotify{}) { t.Errorf("Expecting Kafka config %#v found %#v", kafkaNotify{}, savedNotifyCfg4) } // Set new Webhook notification id. - serverConfig.SetWebhookNotifyByID("2", webhookNotify{}) - savedNotifyCfg5 := serverConfig.GetWebhookNotifyByID("2") + serverConfig.Notify.SetWebhookByID("2", webhookNotify{}) + savedNotifyCfg5 := serverConfig.Notify.GetWebhookByID("2") if !reflect.DeepEqual(savedNotifyCfg5, webhookNotify{}) { t.Errorf("Expecting Webhook config %#v found %#v", webhookNotify{}, savedNotifyCfg3) } // Set new console logger. - serverConfig.SetConsoleLogger(consoleLogger{ + serverConfig.Logger.SetConsole(consoleLogger{ Enable: true, }) - consoleCfg := serverConfig.GetConsoleLogger() + consoleCfg := serverConfig.Logger.GetConsole() if !reflect.DeepEqual(consoleCfg, consoleLogger{Enable: true}) { t.Errorf("Expecting console logger config %#v found %#v", consoleLogger{Enable: true}, consoleCfg) } // Set new file logger. - serverConfig.SetFileLogger(fileLogger{ + serverConfig.Logger.SetFile(fileLogger{ Enable: true, }) - fileCfg := serverConfig.GetFileLogger() + fileCfg := serverConfig.Logger.GetFile() if !reflect.DeepEqual(fileCfg, fileLogger{Enable: true}) { t.Errorf("Expecting file logger config %#v found %#v", fileLogger{Enable: true}, consoleCfg) } diff --git a/cmd/event-notifier.go b/cmd/event-notifier.go index fa3eb5b7b..8ebc5462d 100644 --- a/cmd/event-notifier.go +++ b/cmd/event-notifier.go @@ -531,7 +531,7 @@ func loadAllBucketNotifications(objAPI ObjectLayer) (map[string]*notificationCon func loadAllQueueTargets() (map[string]*logrus.Logger, error) { queueTargets := make(map[string]*logrus.Logger) // Load all amqp targets, initialize their respective loggers. - for accountID, amqpN := range serverConfig.GetAMQP() { + for accountID, amqpN := range serverConfig.Notify.GetAMQP() { if !amqpN.Enable { continue } @@ -558,7 +558,7 @@ func loadAllQueueTargets() (map[string]*logrus.Logger, error) { queueTargets[queueARN] = amqpLog } // Load all nats targets, initialize their respective loggers. - for accountID, natsN := range serverConfig.GetNATS() { + for accountID, natsN := range serverConfig.Notify.GetNATS() { if !natsN.Enable { continue } @@ -586,7 +586,7 @@ func loadAllQueueTargets() (map[string]*logrus.Logger, error) { } // Load redis targets, initialize their respective loggers. - for accountID, redisN := range serverConfig.GetRedis() { + for accountID, redisN := range serverConfig.Notify.GetRedis() { if !redisN.Enable { continue } @@ -614,7 +614,7 @@ func loadAllQueueTargets() (map[string]*logrus.Logger, error) { } // Load Webhook targets, initialize their respective loggers. - for accountID, webhookN := range serverConfig.GetWebhook() { + for accountID, webhookN := range serverConfig.Notify.GetWebhook() { if !webhookN.Enable { continue } @@ -635,7 +635,7 @@ func loadAllQueueTargets() (map[string]*logrus.Logger, error) { } // Load elastic targets, initialize their respective loggers. - for accountID, elasticN := range serverConfig.GetElasticSearch() { + for accountID, elasticN := range serverConfig.Notify.GetElasticSearch() { if !elasticN.Enable { continue } @@ -661,7 +661,7 @@ func loadAllQueueTargets() (map[string]*logrus.Logger, error) { } // Load PostgreSQL targets, initialize their respective loggers. - for accountID, pgN := range serverConfig.GetPostgreSQL() { + for accountID, pgN := range serverConfig.Notify.GetPostgreSQL() { if !pgN.Enable { continue } @@ -686,7 +686,7 @@ func loadAllQueueTargets() (map[string]*logrus.Logger, error) { queueTargets[queueARN] = pgLog } // Load Kafka targets, initialize their respective loggers. - for accountID, kafkaN := range serverConfig.GetKafka() { + for accountID, kafkaN := range serverConfig.Notify.GetKafka() { if !kafkaN.Enable { continue } diff --git a/cmd/event-notifier_test.go b/cmd/event-notifier_test.go index 0b52f65da..415350c24 100644 --- a/cmd/event-notifier_test.go +++ b/cmd/event-notifier_test.go @@ -106,7 +106,7 @@ func TestInitEventNotifierWithPostgreSQL(t *testing.T) { t.Fatal("Unable to initialize FS backend.", err) } - serverConfig.SetPostgreSQLNotifyByID("1", postgreSQLNotify{Enable: true}) + serverConfig.Notify.SetPostgreSQLByID("1", postgreSQLNotify{Enable: true}) if err := initEventNotifier(fs); err == nil { t.Fatal("PostgreSQL config didn't fail.") } @@ -137,7 +137,7 @@ func TestInitEventNotifierWithNATS(t *testing.T) { t.Fatal("Unable to initialize FS backend.", err) } - serverConfig.SetNATSNotifyByID("1", natsNotify{Enable: true}) + serverConfig.Notify.SetNATSByID("1", natsNotify{Enable: true}) if err := initEventNotifier(fs); err == nil { t.Fatal("NATS config didn't fail.") } @@ -168,7 +168,7 @@ func TestInitEventNotifierWithWebHook(t *testing.T) { t.Fatal("Unable to initialize FS backend.", err) } - serverConfig.SetWebhookNotifyByID("1", webhookNotify{Enable: true}) + serverConfig.Notify.SetWebhookByID("1", webhookNotify{Enable: true}) if err := initEventNotifier(fs); err == nil { t.Fatal("WebHook config didn't fail.") } @@ -199,7 +199,7 @@ func TestInitEventNotifierWithAMQP(t *testing.T) { t.Fatal("Unable to initialize FS backend.", err) } - serverConfig.SetAMQPNotifyByID("1", amqpNotify{Enable: true}) + serverConfig.Notify.SetAMQPByID("1", amqpNotify{Enable: true}) if err := initEventNotifier(fs); err == nil { t.Fatal("AMQP config didn't fail.") } @@ -230,7 +230,7 @@ func TestInitEventNotifierWithElasticSearch(t *testing.T) { t.Fatal("Unable to initialize FS backend.", err) } - serverConfig.SetElasticSearchNotifyByID("1", elasticSearchNotify{Enable: true}) + serverConfig.Notify.SetElasticSearchByID("1", elasticSearchNotify{Enable: true}) if err := initEventNotifier(fs); err == nil { t.Fatal("ElasticSearch config didn't fail.") } @@ -261,7 +261,7 @@ func TestInitEventNotifierWithRedis(t *testing.T) { t.Fatal("Unable to initialize FS backend.", err) } - serverConfig.SetRedisNotifyByID("1", redisNotify{Enable: true}) + serverConfig.Notify.SetRedisByID("1", redisNotify{Enable: true}) if err := initEventNotifier(fs); err == nil { t.Fatal("Redis config didn't fail.") } diff --git a/cmd/logger-console-hook.go b/cmd/logger-console-hook.go index 653b6ff04..fdc5264e8 100644 --- a/cmd/logger-console-hook.go +++ b/cmd/logger-console-hook.go @@ -26,7 +26,7 @@ type consoleLogger struct { // enable console logger. func enableConsoleLogger() { - clogger := serverConfig.GetConsoleLogger() + clogger := serverConfig.Logger.GetConsole() if !clogger.Enable { return } diff --git a/cmd/logger-file-hook.go b/cmd/logger-file-hook.go index a0aad40a5..c7b5f6652 100644 --- a/cmd/logger-file-hook.go +++ b/cmd/logger-file-hook.go @@ -35,7 +35,7 @@ type localFile struct { } func enableFileLogger() { - flogger := serverConfig.GetFileLogger() + flogger := serverConfig.Logger.GetFile() if !flogger.Enable || flogger.Filename == "" { return } diff --git a/cmd/logger.go b/cmd/logger.go index 733e5606e..4aba14543 100644 --- a/cmd/logger.go +++ b/cmd/logger.go @@ -39,11 +39,41 @@ var log = struct { // - console [default] // - file type logger struct { + sync.RWMutex Console consoleLogger `json:"console"` File fileLogger `json:"file"` // Add new loggers here. } +/// Logger related. + +// SetFile set new file logger. +func (l *logger) SetFile(flogger fileLogger) { + l.Lock() + defer l.Unlock() + l.File = flogger +} + +// GetFileLogger get current file logger. +func (l *logger) GetFile() fileLogger { + l.RLock() + defer l.RUnlock() + return l.File +} + +// SetConsole set new console logger. +func (l *logger) SetConsole(clogger consoleLogger) { + l.Lock() + defer l.Unlock() + l.Console = clogger +} + +func (l *logger) GetConsole() consoleLogger { + l.RLock() + defer l.RUnlock() + return l.Console +} + // Get file, line, function name of the caller. func callerSource() string { pc, file, line, success := runtime.Caller(2) diff --git a/cmd/notifier-config.go b/cmd/notifier-config.go new file mode 100644 index 000000000..2c9728158 --- /dev/null +++ b/cmd/notifier-config.go @@ -0,0 +1,228 @@ +/* + * Minio Cloud Storage, (C) 2017 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 cmd + +import "sync" + +// Notifier represents collection of supported notification queues. +type notifier struct { + sync.RWMutex + AMQP amqpConfigs `json:"amqp"` + NATS natsConfigs `json:"nats"` + ElasticSearch elasticSearchConfigs `json:"elasticsearch"` + Redis redisConfigs `json:"redis"` + PostgreSQL postgreSQLConfigs `json:"postgresql"` + Kafka kafkaConfigs `json:"kafka"` + Webhook webhookConfigs `json:"webhook"` + // Add new notification queues. +} + +type amqpConfigs map[string]amqpNotify + +func (a amqpConfigs) Clone() amqpConfigs { + a2 := make(amqpConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +type natsConfigs map[string]natsNotify + +func (a natsConfigs) Clone() natsConfigs { + a2 := make(natsConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +type elasticSearchConfigs map[string]elasticSearchNotify + +func (a elasticSearchConfigs) Clone() elasticSearchConfigs { + a2 := make(elasticSearchConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +type redisConfigs map[string]redisNotify + +func (a redisConfigs) Clone() redisConfigs { + a2 := make(redisConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +type postgreSQLConfigs map[string]postgreSQLNotify + +func (a postgreSQLConfigs) Clone() postgreSQLConfigs { + a2 := make(postgreSQLConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +type kafkaConfigs map[string]kafkaNotify + +func (a kafkaConfigs) Clone() kafkaConfigs { + a2 := make(kafkaConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +type webhookConfigs map[string]webhookNotify + +func (a webhookConfigs) Clone() webhookConfigs { + a2 := make(webhookConfigs, len(a)) + for k, v := range a { + a2[k] = v + } + return a2 +} + +func (n *notifier) SetAMQPByID(accountID string, amqpn amqpNotify) { + n.Lock() + defer n.Unlock() + n.AMQP[accountID] = amqpn +} + +func (n *notifier) GetAMQP() map[string]amqpNotify { + n.RLock() + defer n.RUnlock() + return n.AMQP.Clone() +} + +func (n *notifier) GetAMQPByID(accountID string) amqpNotify { + n.RLock() + defer n.RUnlock() + return n.AMQP[accountID] +} + +func (n *notifier) SetNATSByID(accountID string, natsn natsNotify) { + n.Lock() + defer n.Unlock() + n.NATS[accountID] = natsn +} + +func (n *notifier) GetNATS() map[string]natsNotify { + n.RLock() + defer n.RUnlock() + return n.NATS.Clone() +} + +func (n *notifier) GetNATSByID(accountID string) natsNotify { + n.RLock() + defer n.RUnlock() + return n.NATS[accountID] +} + +func (n *notifier) SetElasticSearchByID(accountID string, es elasticSearchNotify) { + n.Lock() + defer n.Unlock() + n.ElasticSearch[accountID] = es +} + +func (n *notifier) GetElasticSearchByID(accountID string) elasticSearchNotify { + n.RLock() + defer n.RUnlock() + return n.ElasticSearch[accountID] +} + +func (n *notifier) GetElasticSearch() map[string]elasticSearchNotify { + n.RLock() + defer n.RUnlock() + return n.ElasticSearch.Clone() +} + +func (n *notifier) SetRedisByID(accountID string, r redisNotify) { + n.Lock() + defer n.Unlock() + n.Redis[accountID] = r +} + +func (n *notifier) GetRedis() map[string]redisNotify { + n.RLock() + defer n.RUnlock() + return n.Redis.Clone() +} + +func (n *notifier) GetRedisByID(accountID string) redisNotify { + n.RLock() + defer n.RUnlock() + return n.Redis[accountID] +} + +func (n *notifier) GetWebhook() map[string]webhookNotify { + n.RLock() + defer n.RUnlock() + return n.Webhook.Clone() +} + +func (n *notifier) GetWebhookByID(accountID string) webhookNotify { + n.RLock() + defer n.RUnlock() + return n.Webhook[accountID] +} + +func (n *notifier) SetWebhookByID(accountID string, pgn webhookNotify) { + n.Lock() + defer n.Unlock() + n.Webhook[accountID] = pgn +} + +func (n *notifier) SetPostgreSQLByID(accountID string, pgn postgreSQLNotify) { + n.Lock() + defer n.Unlock() + n.PostgreSQL[accountID] = pgn +} + +func (n *notifier) GetPostgreSQL() map[string]postgreSQLNotify { + n.RLock() + defer n.RUnlock() + return n.PostgreSQL.Clone() +} + +func (n *notifier) GetPostgreSQLByID(accountID string) postgreSQLNotify { + n.RLock() + defer n.RUnlock() + return n.PostgreSQL[accountID] +} + +func (n *notifier) SetKafkaByID(accountID string, kn kafkaNotify) { + n.Lock() + defer n.Unlock() + n.Kafka[accountID] = kn +} + +func (n *notifier) GetKafka() map[string]kafkaNotify { + n.RLock() + defer n.RUnlock() + return n.Kafka.Clone() +} + +func (n *notifier) GetKafkaByID(accountID string) kafkaNotify { + n.RLock() + defer n.RUnlock() + return n.Kafka[accountID] +} diff --git a/cmd/notifier-config_test.go b/cmd/notifier-config_test.go new file mode 100644 index 000000000..a416825a9 --- /dev/null +++ b/cmd/notifier-config_test.go @@ -0,0 +1,17 @@ +/* + * Minio Cloud Storage, (C) 2017 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 cmd diff --git a/cmd/notifiers.go b/cmd/notifiers.go index f1f1c4cbc..1d3ed1bfd 100644 --- a/cmd/notifiers.go +++ b/cmd/notifiers.go @@ -54,24 +54,12 @@ const ( var errNotifyNotEnabled = errors.New("requested notifier not enabled") -// Notifier represents collection of supported notification queues. -type notifier struct { - AMQP map[string]amqpNotify `json:"amqp"` - NATS map[string]natsNotify `json:"nats"` - ElasticSearch map[string]elasticSearchNotify `json:"elasticsearch"` - Redis map[string]redisNotify `json:"redis"` - PostgreSQL map[string]postgreSQLNotify `json:"postgresql"` - Kafka map[string]kafkaNotify `json:"kafka"` - Webhook map[string]webhookNotify `json:"webhook"` - // Add new notification queues. -} - // Returns true if queueArn is for an AMQP queue. func isAMQPQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypeAMQP { return false } - amqpL := serverConfig.GetAMQPNotifyByID(sqsArn.AccountID) + amqpL := serverConfig.Notify.GetAMQPByID(sqsArn.AccountID) if !amqpL.Enable { return false } @@ -90,7 +78,7 @@ func isNATSQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypeNATS { return false } - natsL := serverConfig.GetNATSNotifyByID(sqsArn.AccountID) + natsL := serverConfig.Notify.GetNATSByID(sqsArn.AccountID) if !natsL.Enable { return false } @@ -109,7 +97,7 @@ func isWebhookQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypeWebhook { return false } - rNotify := serverConfig.GetWebhookNotifyByID(sqsArn.AccountID) + rNotify := serverConfig.Notify.GetWebhookByID(sqsArn.AccountID) if !rNotify.Enable { return false } @@ -121,7 +109,7 @@ func isRedisQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypeRedis { return false } - rNotify := serverConfig.GetRedisNotifyByID(sqsArn.AccountID) + rNotify := serverConfig.Notify.GetRedisByID(sqsArn.AccountID) if !rNotify.Enable { return false } @@ -140,7 +128,7 @@ func isElasticQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypeElastic { return false } - esNotify := serverConfig.GetElasticSearchNotifyByID(sqsArn.AccountID) + esNotify := serverConfig.Notify.GetElasticSearchByID(sqsArn.AccountID) if !esNotify.Enable { return false } @@ -158,7 +146,7 @@ func isPostgreSQLQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypePostgreSQL { return false } - pgNotify := serverConfig.GetPostgreSQLNotifyByID(sqsArn.AccountID) + pgNotify := serverConfig.Notify.GetPostgreSQLByID(sqsArn.AccountID) if !pgNotify.Enable { return false } @@ -176,7 +164,7 @@ func isKafkaQueue(sqsArn arnSQS) bool { if sqsArn.Type != queueTypeKafka { return false } - kafkaNotifyCfg := serverConfig.GetKafkaNotifyByID(sqsArn.AccountID) + kafkaNotifyCfg := serverConfig.Notify.GetKafkaByID(sqsArn.AccountID) if !kafkaNotifyCfg.Enable { return false } diff --git a/cmd/notify-amqp.go b/cmd/notify-amqp.go index a5b87f72d..9168cc959 100644 --- a/cmd/notify-amqp.go +++ b/cmd/notify-amqp.go @@ -59,7 +59,7 @@ func dialAMQP(amqpL amqpNotify) (amqpConn, error) { } func newAMQPNotify(accountID string) (*logrus.Logger, error) { - amqpL := serverConfig.GetAMQPNotifyByID(accountID) + amqpL := serverConfig.Notify.GetAMQPByID(accountID) // Connect to amqp server. amqpC, err := dialAMQP(amqpL) diff --git a/cmd/notify-elasticsearch.go b/cmd/notify-elasticsearch.go index 98249d16d..508b7ed9e 100644 --- a/cmd/notify-elasticsearch.go +++ b/cmd/notify-elasticsearch.go @@ -55,7 +55,7 @@ func dialElastic(esNotify elasticSearchNotify) (*elastic.Client, error) { } func newElasticNotify(accountID string) (*logrus.Logger, error) { - esNotify := serverConfig.GetElasticSearchNotifyByID(accountID) + esNotify := serverConfig.Notify.GetElasticSearchByID(accountID) // Dial to elastic search. client, err := dialElastic(esNotify) diff --git a/cmd/notify-kafka.go b/cmd/notify-kafka.go index d6e5d1f66..7ddf454b8 100644 --- a/cmd/notify-kafka.go +++ b/cmd/notify-kafka.go @@ -75,7 +75,7 @@ func dialKafka(kn kafkaNotify) (kafkaConn, error) { } func newKafkaNotify(accountID string) (*logrus.Logger, error) { - kafkaNotifyCfg := serverConfig.GetKafkaNotifyByID(accountID) + kafkaNotifyCfg := serverConfig.Notify.GetKafkaByID(accountID) // Try connecting to the configured Kafka broker(s). kc, err := dialKafka(kafkaNotifyCfg) diff --git a/cmd/notify-nats.go b/cmd/notify-nats.go index bec7cdcdf..b18751ded 100644 --- a/cmd/notify-nats.go +++ b/cmd/notify-nats.go @@ -127,7 +127,7 @@ func closeNATS(conn natsIOConn) { } func newNATSNotify(accountID string) (*logrus.Logger, error) { - natsL := serverConfig.GetNATSNotifyByID(accountID) + natsL := serverConfig.Notify.GetNATSByID(accountID) // Connect to nats server. natsC, err := dialNATS(natsL, false) diff --git a/cmd/notify-postgresql.go b/cmd/notify-postgresql.go index 5e1634655..116092520 100644 --- a/cmd/notify-postgresql.go +++ b/cmd/notify-postgresql.go @@ -174,7 +174,7 @@ func dialPostgreSQL(pgN postgreSQLNotify) (pgConn, error) { } func newPostgreSQLNotify(accountID string) (*logrus.Logger, error) { - pgNotify := serverConfig.GetPostgreSQLNotifyByID(accountID) + pgNotify := serverConfig.Notify.GetPostgreSQLByID(accountID) // Dial postgres pgC, err := dialPostgreSQL(pgNotify) diff --git a/cmd/notify-redis.go b/cmd/notify-redis.go index f44333cca..8e382edb5 100644 --- a/cmd/notify-redis.go +++ b/cmd/notify-redis.go @@ -83,7 +83,7 @@ func dialRedis(rNotify redisNotify) (*redis.Pool, error) { } func newRedisNotify(accountID string) (*logrus.Logger, error) { - rNotify := serverConfig.GetRedisNotifyByID(accountID) + rNotify := serverConfig.Notify.GetRedisByID(accountID) // Dial redis. rPool, err := dialRedis(rNotify) diff --git a/cmd/notify-webhook.go b/cmd/notify-webhook.go index 875167f79..7bdb8f086 100644 --- a/cmd/notify-webhook.go +++ b/cmd/notify-webhook.go @@ -52,7 +52,7 @@ func lookupEndpoint(u *url.URL) error { // Initializes new webhook logrus notifier. func newWebhookNotify(accountID string) (*logrus.Logger, error) { - rNotify := serverConfig.GetWebhookNotifyByID(accountID) + rNotify := serverConfig.Notify.GetWebhookByID(accountID) if rNotify.Endpoint == "" { return nil, errInvalidArgument diff --git a/cmd/notify-webhook_test.go b/cmd/notify-webhook_test.go index 4740901f0..ff974f751 100644 --- a/cmd/notify-webhook_test.go +++ b/cmd/notify-webhook_test.go @@ -51,13 +51,13 @@ func TestNewWebHookNotify(t *testing.T) { t.Fatal("Unexpected should fail") } - serverConfig.SetWebhookNotifyByID("10", webhookNotify{Enable: true, Endpoint: "http://www."}) + serverConfig.Notify.SetWebhookByID("10", webhookNotify{Enable: true, Endpoint: "http://www."}) _, err = newWebhookNotify("10") if err == nil { t.Fatal("Unexpected should fail with lookupHost") } - serverConfig.SetWebhookNotifyByID("15", webhookNotify{Enable: true, Endpoint: "http://%"}) + serverConfig.Notify.SetWebhookByID("15", webhookNotify{Enable: true, Endpoint: "http://%"}) _, err = newWebhookNotify("15") if err == nil { t.Fatal("Unexpected should fail with invalid URL escape") @@ -66,7 +66,7 @@ func TestNewWebHookNotify(t *testing.T) { server := httptest.NewServer(postHandler{}) defer server.Close() - serverConfig.SetWebhookNotifyByID("20", webhookNotify{Enable: true, Endpoint: server.URL}) + serverConfig.Notify.SetWebhookByID("20", webhookNotify{Enable: true, Endpoint: server.URL}) webhook, err := newWebhookNotify("20") if err != nil { t.Fatal("Unexpected shouldn't fail", err) From 1ad96ee09f7c23c2207098697a4820327b54a1f4 Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Fri, 10 Feb 2017 10:08:14 +0530 Subject: [PATCH 59/75] Handle uptime for single-node instances differnt from distributed setup (#3726) --- cmd/admin-rpc-client.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/admin-rpc-client.go b/cmd/admin-rpc-client.go index 58a83cd0c..a34809560 100644 --- a/cmd/admin-rpc-client.go +++ b/cmd/admin-rpc-client.go @@ -287,6 +287,13 @@ func (ts uptimeSlice) Swap(i, j int) { // getPeerUptimes - returns the uptime since the last time read quorum // was established on success. Otherwise returns errXLReadQuorum. func getPeerUptimes(peers adminPeers) (time.Duration, error) { + // In a single node Erasure or FS backend setup the uptime of + // the setup is the uptime of the single minio server + // instance. + if !globalIsDistXL { + return time.Now().UTC().Sub(globalBootTime), nil + } + uptimes := make(uptimeSlice, len(peers)) // Get up time of all servers. @@ -320,8 +327,9 @@ func getPeerUptimes(peers adminPeers) (time.Duration, error) { } } - // This implies there weren't read quorum number of servers up. - if latestUptime == time.Duration(0) { + // Less than readQuorum "Admin.Uptime" RPC call returned + // successfully, so read-quorum unavailable. + if validCount < readQuorum { return time.Duration(0), InsufficientReadQuorum{} } From 9df01035dabd985e0c7ce084fc2ced0a4250f99b Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 9 Feb 2017 23:26:44 -0800 Subject: [PATCH 60/75] Remove XL references in public docs to Erasure. (#3725) Ref #3722 --- cmd/admin-handlers_test.go | 8 ++++---- cmd/admin-rpc-client.go | 1 + cmd/auth-handler_test.go | 16 ++++++++-------- cmd/config-v13_test.go | 8 ++++++++ cmd/object-api-common_test.go | 8 ++++---- cmd/object-api-datatypes.go | 8 ++++---- cmd/server-main.go | 6 +++--- cmd/server-main_test.go | 32 ++++++++++++++++---------------- cmd/server-startup-msg.go | 2 +- cmd/server-startup-msg_test.go | 2 +- cmd/xl-v1.go | 2 +- docs/backend/README.md | 8 +++++--- docs/minio-limitations.md | 19 ++++++++++--------- pkg/madmin/API.md | 6 +++--- pkg/madmin/service-commands.go | 8 ++++---- 15 files changed, 73 insertions(+), 61 deletions(-) diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index e576a5304..e309e3f27 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -202,7 +202,7 @@ func testServicesCmdHandler(cmd cmdType, t *testing.T) { // Initialize admin peers to make admin RPC calls. Note: In a // single node setup, this degenerates to a simple function // call under the hood. - eps, err := parseStorageEndpoints([]string{"http://localhost"}) + eps, err := parseStorageEndpoints([]string{"http://127.0.0.1"}) if err != nil { t.Fatalf("Failed to parse storage end point - %v", err) } @@ -268,7 +268,7 @@ func TestServiceSetCreds(t *testing.T) { // Initialize admin peers to make admin RPC calls. Note: In a // single node setup, this degenerates to a simple function // call under the hood. - eps, err := parseStorageEndpoints([]string{"http://localhost"}) + eps, err := parseStorageEndpoints([]string{"http://127.0.0.1"}) if err != nil { t.Fatalf("Failed to parse storage end point - %v", err) } @@ -356,7 +356,7 @@ func TestListLocksHandler(t *testing.T) { defer adminTestBed.TearDown() // Initialize admin peers to make admin RPC calls. - eps, err := parseStorageEndpoints([]string{"http://localhost"}) + eps, err := parseStorageEndpoints([]string{"http://127.0.0.1"}) if err != nil { t.Fatalf("Failed to parse storage end point - %v", err) } @@ -431,7 +431,7 @@ func TestClearLocksHandler(t *testing.T) { defer adminTestBed.TearDown() // Initialize admin peers to make admin RPC calls. - eps, err := parseStorageEndpoints([]string{"http://localhost"}) + eps, err := parseStorageEndpoints([]string{"http://127.0.0.1"}) if err != nil { t.Fatalf("Failed to parse storage end point - %v", err) } diff --git a/cmd/admin-rpc-client.go b/cmd/admin-rpc-client.go index a34809560..6cb0709be 100644 --- a/cmd/admin-rpc-client.go +++ b/cmd/admin-rpc-client.go @@ -317,6 +317,7 @@ func getPeerUptimes(peers adminPeers) (time.Duration, error) { latestUptime := time.Duration(0) for _, uptime := range uptimes { if uptime.err != nil { + errorIf(uptime.err, "Unable to fetch uptime") continue } diff --git a/cmd/auth-handler_test.go b/cmd/auth-handler_test.go index c0e85bae2..fbb78d4e2 100644 --- a/cmd/auth-handler_test.go +++ b/cmd/auth-handler_test.go @@ -36,7 +36,7 @@ func TestGetRequestAuthType(t *testing.T) { { req: &http.Request{ URL: &url.URL{ - Host: "localhost:9000", + Host: "127.0.0.1:9000", Scheme: httpScheme, Path: "/", }, @@ -53,7 +53,7 @@ func TestGetRequestAuthType(t *testing.T) { { req: &http.Request{ URL: &url.URL{ - Host: "localhost:9000", + Host: "127.0.0.1:9000", Scheme: httpScheme, Path: "/", }, @@ -68,7 +68,7 @@ func TestGetRequestAuthType(t *testing.T) { { req: &http.Request{ URL: &url.URL{ - Host: "localhost:9000", + Host: "127.0.0.1:9000", Scheme: httpScheme, Path: "/", }, @@ -83,7 +83,7 @@ func TestGetRequestAuthType(t *testing.T) { { req: &http.Request{ URL: &url.URL{ - Host: "localhost:9000", + Host: "127.0.0.1:9000", Scheme: httpScheme, Path: "/", RawQuery: "X-Amz-Credential=EXAMPLEINVALIDEXAMPL%2Fs3%2F20160314%2Fus-east-1", @@ -96,7 +96,7 @@ func TestGetRequestAuthType(t *testing.T) { { req: &http.Request{ URL: &url.URL{ - Host: "localhost:9000", + Host: "127.0.0.1:9000", Scheme: httpScheme, Path: "/", }, @@ -326,11 +326,11 @@ func TestIsReqAuthenticated(t *testing.T) { // When request is nil, internal error is returned. {nil, ErrInternalError}, // When request is unsigned, access denied is returned. - {mustNewRequest("GET", "http://localhost:9000", 0, nil, t), ErrAccessDenied}, + {mustNewRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrAccessDenied}, // When request is properly signed, but has bad Content-MD5 header. - {mustNewSignedRequest("PUT", "http://localhost:9000", 5, bytes.NewReader([]byte("hello")), t), ErrBadDigest}, + {mustNewSignedRequest("PUT", "http://127.0.0.1:9000", 5, bytes.NewReader([]byte("hello")), t), ErrBadDigest}, // When request is properly signed, error is none. - {mustNewSignedRequest("GET", "http://localhost:9000", 0, nil, t), ErrNone}, + {mustNewSignedRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrNone}, } // Validates all testcases. diff --git a/cmd/config-v13_test.go b/cmd/config-v13_test.go index bd505c743..4b4e420f9 100644 --- a/cmd/config-v13_test.go +++ b/cmd/config-v13_test.go @@ -82,6 +82,10 @@ func TestServerConfig(t *testing.T) { if !reflect.DeepEqual(consoleCfg, consoleLogger{Enable: true}) { t.Errorf("Expecting console logger config %#v found %#v", consoleLogger{Enable: true}, consoleCfg) } + // Set new console logger. + serverConfig.Logger.SetConsole(consoleLogger{ + Enable: false, + }) // Set new file logger. serverConfig.Logger.SetFile(fileLogger{ @@ -91,6 +95,10 @@ func TestServerConfig(t *testing.T) { if !reflect.DeepEqual(fileCfg, fileLogger{Enable: true}) { t.Errorf("Expecting file logger config %#v found %#v", fileLogger{Enable: true}, consoleCfg) } + // Set new file logger. + serverConfig.Logger.SetFile(fileLogger{ + Enable: false, + }) // Match version. if serverConfig.GetVersion() != globalMinioConfigVersion { diff --git a/cmd/object-api-common_test.go b/cmd/object-api-common_test.go index d312901c5..784044088 100644 --- a/cmd/object-api-common_test.go +++ b/cmd/object-api-common_test.go @@ -116,8 +116,8 @@ func TestGetPath(t *testing.T) { {"D:\\", "d:\\"}, {"D:", "d:"}, {"\\", "\\"}, - {"http://localhost/d:/export", "d:/export"}, - {"https://localhost/d:/export", "d:/export"}, + {"http://127.0.0.1/d:/export", "d:/export"}, + {"https://127.0.0.1/d:/export", "d:/export"}, } } else { testCases = []struct { @@ -125,8 +125,8 @@ func TestGetPath(t *testing.T) { path string }{ {"/export", "/export"}, - {"http://localhost/export", "/export"}, - {"https://localhost/export", "/export"}, + {"http://127.0.0.1/export", "/export"}, + {"https://127.0.0.1/export", "/export"}, } } testCasesCommon := []struct { diff --git a/cmd/object-api-datatypes.go b/cmd/object-api-datatypes.go index cdb052f29..307220f4d 100644 --- a/cmd/object-api-datatypes.go +++ b/cmd/object-api-datatypes.go @@ -26,8 +26,8 @@ const ( Unknown BackendType = iota // Filesystem backend. FS - // Multi disk XL (single, distributed) backend. - XL + // Multi disk Erasure (single, distributed) backend. + Erasure // Add your own backend. ) @@ -39,10 +39,10 @@ type StorageInfo struct { Free int64 // Backend type. Backend struct { - // Represents various backend types, currently on FS and XL. + // Represents various backend types, currently on FS and Erasure. Type BackendType - // Following fields are only meaningful if BackendType is XL. + // Following fields are only meaningful if BackendType is Erasure. OnlineDisks int // Online disks during server startup. OfflineDisks int // Offline disks during server startup. ReadQuorum int // Minimum disks required for successful read operations. diff --git a/cmd/server-main.go b/cmd/server-main.go index 3d6602604..6b4deca7f 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -466,12 +466,12 @@ func serverMain(c *cli.Context) { globalObjectAPI = newObject globalObjLayerMutex.Unlock() - // Set startup time - globalBootTime = time.Now().UTC() - // Prints the formatted startup message once object layer is initialized. printStartupMessage(apiEndPoints) + // Set uptime time after object layer has initialized. + globalBootTime = time.Now().UTC() + // Waits on the server. <-globalServiceDoneCh } diff --git a/cmd/server-main_test.go b/cmd/server-main_test.go index cf49c9086..84416bb62 100644 --- a/cmd/server-main_test.go +++ b/cmd/server-main_test.go @@ -33,7 +33,7 @@ func TestGetListenIPs(t *testing.T) { port string shouldPass bool }{ - {"localhost", "9000", true}, + {"127.0.0.1", "9000", true}, {"", "9000", true}, {"", "", false}, } @@ -114,8 +114,8 @@ func TestFinalizeAPIEndpoints(t *testing.T) { }{ {":80"}, {":80"}, - {"localhost:80"}, - {"localhost:80"}, + {"127.0.0.1:80"}, + {"127.0.0.1:80"}, } for i, test := range testCases { @@ -283,18 +283,18 @@ func TestParseStorageEndpoints(t *testing.T) { host string expectedErr error }{ - {"", "http://localhost/export", nil}, + {"", "http://127.0.0.1/export", nil}, { "testhost", - "http://localhost/export", - errors.New("Invalid Argument localhost, port mandatory when --address : is used"), + "http://127.0.0.1/export", + errors.New("Invalid Argument 127.0.0.1, port mandatory when --address : is used"), }, { "", - "http://localhost:9000/export", - errors.New("Invalid Argument localhost:9000, port configurable using --address :"), + "http://127.0.0.1:9000/export", + errors.New("Invalid Argument 127.0.0.1:9000, port configurable using --address :"), }, - {"testhost", "http://localhost:9000/export", nil}, + {"testhost", "http://127.0.0.1:9000/export", nil}, } for i, test := range testCases { globalMinioHost = test.globalMinioHost @@ -315,15 +315,15 @@ func TestCheckEndpointsSyntax(t *testing.T) { successCases := []string{ "export", "/export", - "http://localhost/export", - "https://localhost/export", + "http://127.0.0.1/export", + "https://127.0.0.1/export", } failureCases := []string{ "/", - "http://localhost", - "http://localhost/", - "ftp://localhost/export", + "http://127.0.0.1", + "http://127.0.0.1/", + "ftp://127.0.0.1/export", "server:/export", } @@ -495,8 +495,8 @@ func TestIsAnyEndpointLocal(t *testing.T) { result: false, }, { - disks: []string{"http://localhost/mnt/disk1", - "http://localhost/mnt/disk1"}, + disks: []string{"http://127.0.0.1/mnt/disk1", + "http://127.0.0.1/mnt/disk1"}, result: true, }, } diff --git a/cmd/server-startup-msg.go b/cmd/server-startup-msg.go index 0cb7370de..55012fc7c 100644 --- a/cmd/server-startup-msg.go +++ b/cmd/server-startup-msg.go @@ -141,7 +141,7 @@ func getStorageInfoMsg(storageInfo StorageInfo) string { msg := fmt.Sprintf("%s %s Free, %s Total", colorBlue("Drive Capacity:"), humanize.IBytes(uint64(storageInfo.Free)), humanize.IBytes(uint64(storageInfo.Total))) - if storageInfo.Backend.Type == XL { + if storageInfo.Backend.Type == Erasure { diskInfo := fmt.Sprintf(" %d Online, %d Offline. ", storageInfo.Backend.OnlineDisks, storageInfo.Backend.OfflineDisks) if maxDiskFailures := storageInfo.Backend.ReadQuorum - storageInfo.Backend.OfflineDisks; maxDiskFailures >= 0 { diskInfo += fmt.Sprintf("We can withstand [%d] more drive failure(s).", maxDiskFailures) diff --git a/cmd/server-startup-msg_test.go b/cmd/server-startup-msg_test.go index bd15cd1e4..ef39b9e18 100644 --- a/cmd/server-startup-msg_test.go +++ b/cmd/server-startup-msg_test.go @@ -38,7 +38,7 @@ func TestStorageInfoMsg(t *testing.T) { OfflineDisks int ReadQuorum int WriteQuorum int - }{XL, 7, 1, 4, 5}, + }{Erasure, 7, 1, 4, 5}, } if msg := getStorageInfoMsg(infoStorage); !strings.Contains(msg, "2.0 GiB Free, 10 GiB Total") || !strings.Contains(msg, "7 Online, 1 Offline") { diff --git a/cmd/xl-v1.go b/cmd/xl-v1.go index a94cdd05a..4f6083d75 100644 --- a/cmd/xl-v1.go +++ b/cmd/xl-v1.go @@ -244,7 +244,7 @@ func getStorageInfo(disks []StorageAPI) StorageInfo { Free: validDisksInfo[0].Free * int64(onlineDisks) / 2, } - storageInfo.Backend.Type = XL + storageInfo.Backend.Type = Erasure storageInfo.Backend.OnlineDisks = onlineDisks storageInfo.Backend.OfflineDisks = offlineDisks return storageInfo diff --git a/docs/backend/README.md b/docs/backend/README.md index c0412b288..548234b37 100644 --- a/docs/backend/README.md +++ b/docs/backend/README.md @@ -1,6 +1,8 @@ ## Backends -Minio currently implements two types of backends namely. +Minio currently implements two types of backends. -- Filesystem layer (fs). -- ErasureCode layer (XL). +| Minio | FS | Erasure | Stability | +|:-----------:|:----:|:----:|:---:| +| Standalone | x | x | Stable | +| Distributed | x | x | Stable | diff --git a/docs/minio-limitations.md b/docs/minio-limitations.md index d7f49e660..9e59ee747 100644 --- a/docs/minio-limitations.md +++ b/docs/minio-limitations.md @@ -1,5 +1,4 @@ ## Minio Server Limits Per Tenant -We found the following APIs to be redundant or less useful outside of AWS. If you have a different view on any of the APIs we missed, please open a [github issue](https://github.com/minio/minio/issues). ### Erasure Code (Multiple Drives / Servers) @@ -31,19 +30,21 @@ We found the following APIs to be redundant or less useful outside of AWS. If yo |Maximum number of objects returned per list objects request| 1000| |Maximum number of multipart uploads returned per list multipart uploads request| 1000| +We found the following APIs to be redundant or less useful outside of AWS S3. If you have a different view on any of the APIs we missed, please open a [github issue](https://github.com/minio/minio/issues). + ### List of Amazon S3 Bucket API's not supported on Minio. -- BucketACL (Use bucket policies instead) -- BucketCORS (CORS enabled by default) -- BucketLifecycle (Not required for Minio's XL backend) -- BucketReplication (Use `mc mirror` instead) -- BucketVersions, BucketVersioning (Use `s3git`) -- BucketWebsite (Use `caddy` or `nginx`) -- BucketAnalytics, BucketMetrics, BucketLogging (Use bucket notification APIs) +- BucketACL (Use [bucket policies](http://docs.minio.io/docs/minio-client-complete-guide#policy) instead) +- BucketCORS (CORS enabled by default on all buckets for all HTTP verbs) +- BucketLifecycle (Not required for Minio erasure coded backend) +- BucketReplication (Use [`mc mirror`](http://docs.minio.io/docs/minio-client-complete-guide#mirror) instead) +- BucketVersions, BucketVersioning (Use [`s3git`](https://github.com/s3git/s3git)) +- BucketWebsite (Use [`caddy`](https://github.com/mholt/caddy) or [`nginx`](https://www.nginx.com/resources/wiki/)) +- BucketAnalytics, BucketMetrics, BucketLogging (Use [bucket notification](http://docs.minio.io/docs/minio-client-complete-guide#events) APIs) - BucketRequestPayment - BucketTagging ### List of Amazon S3 Object API's not supported on Minio. -- ObjectACL (Use bucket policies instead) +- ObjectACL (Use [bucket policies](http://docs.minio.io/docs/minio-client-complete-guide#policy) instead) - ObjectTorrent diff --git a/pkg/madmin/API.md b/pkg/madmin/API.md index 36c79b1a2..506690783 100644 --- a/pkg/madmin/API.md +++ b/pkg/madmin/API.md @@ -82,9 +82,9 @@ Fetch service status, replies disk space used, backend type and total disks offl | Param | Type | Description | |---|---|---| -|`backend.Type` | _BackendType_ | Type of backend used by the server currently only FS or XL. | -|`backend.OnlineDisks`| _int_ | Total number of disks online (only applies to XL backend), is empty for FS. | -|`backend.OfflineDisks` | _int_ | Total number of disks offline (only applies to XL backend), is empty for FS. | +|`backend.Type` | _BackendType_ | Type of backend used by the server currently only FS or Erasure. | +|`backend.OnlineDisks`| _int_ | Total number of disks online (only applies to Erasure backend), is empty for FS. | +|`backend.OfflineDisks` | _int_ | Total number of disks offline (only applies to Erasure backend), is empty for FS. | |`backend.ReadQuorum` | _int_ | Current total read quorum threshold before reads will be unavailable, is empty for FS. | |`backend.WriteQuorum` | _int_ | Current total write quorum threshold before writes will be unavailable, is empty for FS. | diff --git a/pkg/madmin/service-commands.go b/pkg/madmin/service-commands.go index 2556a8960..292340ed7 100644 --- a/pkg/madmin/service-commands.go +++ b/pkg/madmin/service-commands.go @@ -36,8 +36,8 @@ const ( Unknown BackendType = iota // Filesystem backend. FS - // Multi disk XL (single, distributed) backend. - XL + // Multi disk Erasure (single, distributed) backend. + Erasure // Add your own backend. ) @@ -50,10 +50,10 @@ type StorageInfo struct { Free int64 // Backend type. Backend struct { - // Represents various backend types, currently on FS and XL. + // Represents various backend types, currently on FS and Erasure. Type BackendType - // Following fields are only meaningful if BackendType is XL. + // Following fields are only meaningful if BackendType is Erasure. OnlineDisks int // Online disks during server startup. OfflineDisks int // Offline disks during server startup. ReadQuorum int // Minimum disks required for successful read operations. From a79935192651174da9f414e78c9b2f688e4f433d Mon Sep 17 00:00:00 2001 From: Karthic Rao Date: Fri, 10 Feb 2017 14:07:22 +0530 Subject: [PATCH 61/75] Fix macOS builds (#3728) --- pkg/disk/type_darwin.go | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 pkg/disk/type_darwin.go diff --git a/pkg/disk/type_darwin.go b/pkg/disk/type_darwin.go deleted file mode 100644 index 85cad1aa7..000000000 --- a/pkg/disk/type_darwin.go +++ /dev/null @@ -1,36 +0,0 @@ -// +build darwin - -/* - * Minio Cloud Storage, (C) 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 disk - -import "strconv" - -// fsType2StrinMap - list of filesystems supported by donut -var fsType2StringMap = map[string]string{ - "11": "HFS", -} - -// getFSType returns the filesystem type of the underlying mounted filesystem -func getFSType(ftype int64) string { - fsTypeHex := strconv.FormatInt(ftype, 16) - fsTypeString, ok := fsType2StringMap[fsTypeHex] - if !ok { - return "UNKNOWN" - } - return fsTypeString -} From 8912b6bf3b22ff668b6448742cd50e7b837182ec Mon Sep 17 00:00:00 2001 From: Bala FA Date: Sat, 11 Feb 2017 01:21:41 +0530 Subject: [PATCH 62/75] trie: new package (#3729) This implements a simple trie tree for minio server/tools. This package borrows idea from https://godoc.org/golang.org/x/text/internal/triegen. --- cmd/commands.go | 7 ++- cmd/main.go | 2 +- {cmd => pkg/trie}/trie.go | 80 ++++++++++++++++++---------------- {cmd => pkg/trie}/trie_test.go | 12 ++--- 4 files changed, 55 insertions(+), 46 deletions(-) rename {cmd => pkg/trie}/trie.go (58%) rename {cmd => pkg/trie}/trie_test.go (89%) diff --git a/cmd/commands.go b/cmd/commands.go index 96aa05ec0..b74f33f4a 100644 --- a/cmd/commands.go +++ b/cmd/commands.go @@ -16,13 +16,16 @@ package cmd -import "github.com/minio/cli" +import ( + "github.com/minio/cli" + "github.com/minio/minio/pkg/trie" +) // Collection of minio commands currently supported are. var commands = []cli.Command{} // Collection of minio commands currently supported in a trie tree. -var commandsTree = newTrie() +var commandsTree = trie.NewTrie() // registerCommand registers a cli command. func registerCommand(command cli.Command) { diff --git a/cmd/main.go b/cmd/main.go index e6db20ad6..5bfb8f77b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -94,7 +94,7 @@ func findClosestCommands(command string) []string { sort.Strings(closestCommands) // Suggest other close commands - allow missed, wrongly added and // even transposed characters - for _, value := range commandsTree.walk(commandsTree.root) { + for _, value := range commandsTree.Walk(commandsTree.Root()) { if sort.SearchStrings(closestCommands, value.(string)) < len(closestCommands) { continue } diff --git a/cmd/trie.go b/pkg/trie/trie.go similarity index 58% rename from cmd/trie.go rename to pkg/trie/trie.go index fb84c3556..d32858c13 100644 --- a/cmd/trie.go +++ b/pkg/trie/trie.go @@ -1,5 +1,5 @@ /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2014, 2015, 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,80 +14,78 @@ * limitations under the License. */ -package cmd +// Package trie implements a simple trie tree for minio server/tools borrows +// idea from - https://godoc.org/golang.org/x/text/internal/triegen. +package trie -// This package borrows idea from - https://godoc.org/golang.org/x/text/internal/triegen +// Node trie tree node container carries value and children. +type Node struct { + exists bool + value interface{} + child map[rune]*Node // runes as child. +} -// Trie trie container +// newNode create a new trie node. +func newNode() *Node { + return &Node{ + exists: false, + value: nil, + child: make(map[rune]*Node), + } +} + +// Trie is a trie container. type Trie struct { - root *trieNode + root *Node size int } -// newTrie get new trie -func newTrie() *Trie { - return &Trie{ - root: newTrieNode(), - size: 0, - } +// Root returns root node. +func (t *Trie) Root() *Node { + return t.root } -// trieNode trie tree node container carries value and children -type trieNode struct { - exists bool - value interface{} - child map[rune]*trieNode // runes as child -} - -func newTrieNode() *trieNode { - return &trieNode{ - exists: false, - value: nil, - child: make(map[rune]*trieNode), - } -} - -// Insert insert a key +// Insert insert a key. func (t *Trie) Insert(key string) { curNode := t.root for _, v := range key { if curNode.child[v] == nil { - curNode.child[v] = newTrieNode() + curNode.child[v] = newNode() } curNode = curNode.child[v] } if !curNode.exists { - // increment when new rune child is added + // increment when new rune child is added. t.size++ curNode.exists = true } - // value is stored for retrieval in future + // value is stored for retrieval in future. curNode.value = key } -// PrefixMatch - prefix match +// PrefixMatch - prefix match. func (t *Trie) PrefixMatch(key string) []interface{} { node, _ := t.findNode(key) if node != nil { - return t.walk(node) + return t.Walk(node) } return []interface{}{} } -// walk the tree -func (t *Trie) walk(node *trieNode) (ret []interface{}) { +// Walk the tree. +func (t *Trie) Walk(node *Node) (ret []interface{}) { if node.exists { ret = append(ret, node.value) } for _, v := range node.child { - ret = append(ret, t.walk(v)...) + ret = append(ret, t.Walk(v)...) } return } -// find nodes corresponding to key -func (t *Trie) findNode(key string) (node *trieNode, index int) { +// find nodes corresponding to key. +func (t *Trie) findNode(key string) (node *Node, index int) { curNode := t.root f := false for k, v := range key { @@ -110,3 +108,11 @@ func (t *Trie) findNode(key string) (node *trieNode, index int) { return curNode, index } + +// NewTrie create a new trie. +func NewTrie() *Trie { + return &Trie{ + root: newNode(), + size: 0, + } +} diff --git a/cmd/trie_test.go b/pkg/trie/trie_test.go similarity index 89% rename from cmd/trie_test.go rename to pkg/trie/trie_test.go index b37093144..454b898e0 100644 --- a/cmd/trie_test.go +++ b/pkg/trie/trie_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package cmd +package trie import ( "testing" @@ -23,7 +23,7 @@ import ( // Simply make sure creating a new tree works. func TestNewTrie(t *testing.T) { var trie *Trie - trie = newTrie() + trie = NewTrie() if trie.size != 0 { t.Errorf("expected size 0, got: %d", trie.size) @@ -33,7 +33,7 @@ func TestNewTrie(t *testing.T) { // Ensure that we can insert new keys into the tree, then check the size. func TestInsert(t *testing.T) { var trie *Trie - trie = newTrie() + trie = NewTrie() // We need to have an empty tree to begin with. if trie.size != 0 { @@ -52,10 +52,10 @@ func TestInsert(t *testing.T) { // Ensure that PrefixMatch gives us the correct two keys in the tree. func TestPrefixMatch(t *testing.T) { var trie *Trie - trie = newTrie() + trie = NewTrie() // Feed it some fodder: only 'minio' and 'miny-os' should trip the matcher. - trie.Insert(globalMinioDefaultOwnerID) + trie.Insert("minio") trie.Insert("amazon") trie.Insert("cheerio") trie.Insert("miny-o's") @@ -65,7 +65,7 @@ func TestPrefixMatch(t *testing.T) { t.Errorf("expected two matches, got: %d", len(matches)) } - if matches[0] != globalMinioDefaultOwnerID && matches[1] != globalMinioDefaultOwnerID { + if matches[0] != "minio" && matches[1] != "minio" { t.Errorf("expected one match to be 'minio', got: '%s' and '%s'", matches[0], matches[1]) } } From 8f66cfa316ae92ceb0492d30c9b888e3a01f1fc7 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Sat, 11 Feb 2017 12:23:17 +0530 Subject: [PATCH 63/75] Fix https://github.com/minio/minio/issues/3453 (#3733) --- docs/distributed/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/distributed/README.md b/docs/distributed/README.md index 2b5189be3..de8ba314b 100644 --- a/docs/distributed/README.md +++ b/docs/distributed/README.md @@ -38,9 +38,10 @@ Install Minio - [Minio Quickstart Guide](https://docs.minio.io/docs/minio-quicks To start a distributed Minio instance, you just need to pass drive locations as parameters to the minio server command. Then, you’ll need to run the same command on all the participating nodes. -It is important to note here that all the nodes running distributed Minio need to have same access key and secret key. Otherwise nodes won't connect. To achieve this, you need to export access key and secret key as environment variables on all the nodes before executing Minio server command. - -Below examples will clarify further: +*Note* +- All the nodes running distributed Minio need to have same access key and secret key for the nodes to connect. To achieve this, you need to export access key and secret key as environment variables on all the nodes before executing Minio server command. +- Disks used for Minio distributed should be fresh with no pre-existing data. +- The IP addresses and drive paths below are for demonstration purposes only, you need to replace these with the actual IP addresses and drive paths/folders. Example 1: Start distributed Minio instance with 1 drive each on 8 nodes, by running this command on all the 8 nodes. @@ -72,8 +73,6 @@ minio server http://192.168.1.11/export1 http://192.168.1.11/export2 \ ![Distributed Minio, 4 nodes with 4 disks each](https://raw.githubusercontent.com/minio/minio/master/docs/screenshots/Architecture-diagram_distributed_16.png) -Note that these IP addresses and drive paths are for demonstration purposes only, you need to replace these with the actual IP addresses and drive paths. - ## 3. Test your setup To test this setup, access the Minio server via browser or [`mc`](https://docs.minio.io/docs/minio-client-quickstart-guide). You’ll see the combined capacity of all the storage drives as the capacity of this drive. From 25b936c369144e12718e0fa0d0d28c0854c31c5f Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Fri, 10 Feb 2017 22:54:42 -0800 Subject: [PATCH 64/75] browser: Implement infinite scrolling for object listing. (#3720) fixes #2831 --- browser/app/js/actions.js | 59 +++++++++++++++++++++++++---- browser/app/js/components/Browse.js | 31 +++++++++------ browser/app/js/components/Path.js | 2 +- browser/app/js/reducers.js | 16 +++++++- browser/package.json | 2 + cmd/web-handlers.go | 51 ++++++++++++------------- 6 files changed, 114 insertions(+), 47 deletions(-) diff --git a/browser/app/js/actions.js b/browser/app/js/actions.js index 979f1ad97..2acf688e1 100644 --- a/browser/app/js/actions.js +++ b/browser/app/js/actions.js @@ -56,6 +56,7 @@ export const SET_POLICIES = 'SET_POLICIES' export const SET_SHARE_OBJECT = 'SET_SHARE_OBJECT' export const DELETE_CONFIRMATION = 'DELETE_CONFIRMATION' export const SET_PREFIX_WRITABLE = 'SET_PREFIX_WRITABLE' +export const REMOVE_OBJECT = 'REMOVE_OBJECT' export const showDeleteConfirmation = (object) => { return { @@ -206,6 +207,13 @@ export const showAlert = alert => { } } +export const removeObject = object => { + return { + type: REMOVE_OBJECT, + object + } +} + export const setSidebarStatus = (status) => { return { type: SET_SIDEBAR_STATUS, @@ -227,10 +235,12 @@ export const setVisibleBuckets = visibleBuckets => { } } -export const setObjects = (objects) => { +export const setObjects = (objects, marker, istruncated) => { return { type: SET_OBJECTS, - objects + objects, + marker, + istruncated } } @@ -284,22 +294,55 @@ export const selectBucket = (newCurrentBucket, prefix) => { } } +export const listObjects = () => { + return (dispatch, getState) => { + const {currentBucket, currentPath, marker, objects, istruncated, web} = getState() + if (!istruncated) return + web.ListObjects({ + bucketName: currentBucket, + prefix: currentPath, + marker: marker + }) + .then(res => { + let objects = res.objects + if (!objects.length) + objects = [] + dispatch(setObjects(objects, res.nextmarker, res.istruncated)) + dispatch(setPrefixWritable(res.writable)) + dispatch(setLoadBucket('')) + dispatch(setLoadPath('')) + }) + .catch(err => { + dispatch(showAlert({ + type: 'danger', + message: err.message + })) + dispatch(setLoadBucket('')) + dispatch(setLoadPath('')) + // Use browserHistory.replace instead of push so that browser back button works fine. + browserHistory.replace(`${minioBrowserPrefix}/login`) + }) + } +} + export const selectPrefix = prefix => { return (dispatch, getState) => { const {currentBucket, web} = getState() + dispatch(setObjects([], "", true)) dispatch(setLoadPath(prefix)) web.ListObjects({ bucketName: currentBucket, - prefix + prefix, + marker: "" }) .then(res => { let objects = res.objects if (!objects) objects = [] dispatch(setObjects( - utils.sortObjectsByName(objects.map(object => { - object.name = object.name.replace(`${prefix}`, ''); return object - })) + objects, + res.nextmarker, + res.istruncated )) dispatch(setPrefixWritable(res.writable)) dispatch(setSortNameOrder(false)) @@ -314,8 +357,8 @@ export const selectPrefix = prefix => { })) dispatch(setLoadBucket('')) dispatch(setLoadPath('')) - // Use browserHistory.replace instead of push so that browser back button works fine. - browserHistory.replace(`${minioBrowserPrefix}/login`) + // Use browserHistory.replace instead of push so that browser back button works fine. + browserHistory.replace(`${minioBrowserPrefix}/login`) }) } } diff --git a/browser/app/js/components/Browse.js b/browser/app/js/components/Browse.js index 128b6c8c2..6458ad22b 100644 --- a/browser/app/js/components/Browse.js +++ b/browser/app/js/components/Browse.js @@ -47,6 +47,7 @@ import * as mime from '../mime' import { minioBrowserPrefix } from '../constants' import CopyToClipboard from 'react-copy-to-clipboard' import storage from 'local-storage-fallback' +import InfiniteScroll from 'react-infinite-scroller'; export default class Browse extends React.Component { componentDidMount() { @@ -110,9 +111,6 @@ export default class Browse extends React.Component { if (!decPathname.endsWith('/')) decPathname += '/' if (decPathname === minioBrowserPrefix + '/') { - dispatch(actions.setCurrentBucket('')) - dispatch(actions.setCurrentPath('')) - dispatch(actions.setObjects([])) return } let obj = utils.pathSlice(decPathname) @@ -140,6 +138,11 @@ export default class Browse extends React.Component { this.props.dispatch(actions.setVisibleBuckets(buckets.filter(bucket => bucket.indexOf(e.target.value) > -1))) } + listObjects() { + const {dispatch} = this.props + dispatch(actions.listObjects()) + } + selectPrefix(e, prefix) { e.preventDefault() const {dispatch, currentPath, web, currentBucket} = this.props @@ -231,7 +234,7 @@ export default class Browse extends React.Component { }) .then(() => { this.hideDeleteConfirmation() - dispatch(actions.selectPrefix(currentPath)) + dispatch(actions.removeObject(deleteConfirmation.object)) }) .catch(e => dispatch(actions.showAlert({ type: 'danger', @@ -360,7 +363,6 @@ export default class Browse extends React.Component { } } - render() { const {total, free} = this.props.storageInfo const {showMakeBucketModal, alert, sortNameOrder, sortSizeOrder, sortDateOrder, showAbout, showBucketPolicy} = this.props @@ -370,7 +372,7 @@ export default class Browse extends React.Component { const {policies, currentBucket, currentPath} = this.props const {deleteConfirmation} = this.props const {shareObject} = this.props - const {web, prefixWritable} = this.props + const {web, prefixWritable, istruncated} = this.props // Don't always show the SettingsModal. This is done here instead of in // SettingsModal.js so as to allow for #componentWillMount to handle @@ -476,7 +478,6 @@ export default class Browse extends React.Component { - } return ( @@ -545,10 +546,18 @@ export default class Browse extends React.Component {
    - + + + +
    + Loading... +
    { createButton } diff --git a/browser/app/js/components/Path.js b/browser/app/js/components/Path.js index 6ca85869b..901f094aa 100644 --- a/browser/app/js/components/Path.js +++ b/browser/app/js/components/Path.js @@ -29,7 +29,7 @@ let Path = ({currentBucket, currentPath, selectPrefix}) => { } return ( -

    selectPrefix(e, '') } href="">{ currentBucket }{ path }

    +

    selectPrefix(e, '') } href="">{ currentBucket }{ path }

    ) } diff --git a/browser/app/js/reducers.js b/browser/app/js/reducers.js index 00482e1ff..ca312fbe7 100644 --- a/browser/app/js/reducers.js +++ b/browser/app/js/reducers.js @@ -21,6 +21,7 @@ export default (state = { buckets: [], visibleBuckets: [], objects: [], + istruncated: true, storageInfo: {}, serverInfo: {}, currentBucket: '', @@ -76,7 +77,15 @@ export default (state = { newState.currentBucket = action.currentBucket break case actions.SET_OBJECTS: - newState.objects = action.objects + if (!action.objects.length) { + newState.objects = [] + newState.marker = "" + newState.istruncated = action.istruncated + } else { + newState.objects = [...newState.objects, ...action.objects] + newState.marker = action.marker + newState.istruncated = action.istruncated + } break case actions.SET_CURRENT_PATH: newState.currentPath = action.currentPath @@ -171,6 +180,11 @@ export default (state = { case actions.SET_PREFIX_WRITABLE: newState.prefixWritable = action.prefixWritable break + case actions.REMOVE_OBJECT: + let idx = newState.objects.findIndex(object => object.name === action.object) + if (idx == -1) break + newState.objects = [...newState.objects.slice(0, idx), ...newState.objects.slice(idx + 1)] + break } return newState } diff --git a/browser/package.json b/browser/package.json index 23e8145c6..583d87621 100644 --- a/browser/package.json +++ b/browser/package.json @@ -32,6 +32,7 @@ "copy-webpack-plugin": "^0.3.3", "css-loader": "^0.23.1", "esformatter": "^0.10.0", + "esformatter-jsx": "^7.4.1", "esformatter-jsx-ignore": "^1.0.6", "expect": "^1.20.2", "history": "^1.17.0", @@ -77,6 +78,7 @@ "react-custom-scrollbars": "^2.2.2", "react-dom": "^0.14.6", "react-dropzone": "^3.5.3", + "react-infinite-scroller": "^1.0.6", "react-onclickout": "2.0.4" } } diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index e11743e94..c988ab835 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -178,13 +178,16 @@ func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, re type ListObjectsArgs struct { BucketName string `json:"bucketName"` Prefix string `json:"prefix"` + Marker string `json:"marker"` } // ListObjectsRep - list objects response. type ListObjectsRep struct { - Objects []WebObjectInfo `json:"objects"` - Writable bool `json:"writable"` // Used by client to show "upload file" button. - UIVersion string `json:"uiVersion"` + Objects []WebObjectInfo `json:"objects"` + NextMarker string `json:"nextmarker"` + IsTruncated bool `json:"istruncated"` + Writable bool `json:"writable"` // Used by client to show "upload file" button. + UIVersion string `json:"uiVersion"` } // WebObjectInfo container for list objects metadata. @@ -226,30 +229,26 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r default: return errAuthentication } - marker := "" - for { - lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, marker, "/", 1000) - if err != nil { - return &json2.Error{Message: err.Error()} - } - marker = lo.NextMarker - for _, obj := range lo.Objects { - reply.Objects = append(reply.Objects, WebObjectInfo{ - Key: obj.Name, - LastModified: obj.ModTime, - Size: obj.Size, - ContentType: obj.ContentType, - }) - } - for _, prefix := range lo.Prefixes { - reply.Objects = append(reply.Objects, WebObjectInfo{ - Key: prefix, - }) - } - if !lo.IsTruncated { - break - } + lo, err := objectAPI.ListObjects(args.BucketName, args.Prefix, args.Marker, slashSeparator, 1000) + if err != nil { + return &json2.Error{Message: err.Error()} } + reply.NextMarker = lo.NextMarker + reply.IsTruncated = lo.IsTruncated + for _, obj := range lo.Objects { + reply.Objects = append(reply.Objects, WebObjectInfo{ + Key: obj.Name, + LastModified: obj.ModTime, + Size: obj.Size, + ContentType: obj.ContentType, + }) + } + for _, prefix := range lo.Prefixes { + reply.Objects = append(reply.Objects, WebObjectInfo{ + Key: prefix, + }) + } + return nil } From 440866d26c64f9fc2616fa87a532c57999939ebb Mon Sep 17 00:00:00 2001 From: Bala FA Date: Sat, 11 Feb 2017 14:57:27 +0530 Subject: [PATCH 65/75] Move go version check into main() (#3734) Previously the check was done in init(). This patch moves into main for unit testable friendly function. --- Makefile | 1 + cmd/globals.go | 5 ----- cmd/main.go | 6 ------ cmd/runtime-checks.go | 45 -------------------------------------- main.go | 38 +++++++++++++++++++++++++++++++- main_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 88 insertions(+), 57 deletions(-) delete mode 100644 cmd/runtime-checks.go create mode 100644 main_test.go diff --git a/Makefile b/Makefile index 57bdf888e..f9eb341fa 100644 --- a/Makefile +++ b/Makefile @@ -107,6 +107,7 @@ spelling: test: build @echo "Running all minio testing:" + @go test $(GOFLAGS) . @go test $(GOFLAGS) github.com/minio/minio/cmd... @go test $(GOFLAGS) github.com/minio/minio/pkg... diff --git a/cmd/globals.go b/cmd/globals.go index f143d531c..56439f635 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -31,11 +31,6 @@ import ( "github.com/minio/minio/pkg/objcache" ) -// Global constants for Minio. -const ( - minGoVersion = ">= 1.7" // Minio requires at least Go v1.7 -) - // minio configuration related constants. const ( globalMinioConfigVersion = "13" diff --git a/cmd/main.go b/cmd/main.go index 5bfb8f77b..31d2d8047 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -65,12 +65,6 @@ VERSION: ` + Version + `{{ "\n"}}` -// init - check the environment before main starts -func init() { - // Check if minio was compiled using a supported version of Golang. - checkGoVersion() -} - func migrate() { // Migrate config file err := migrateConfig() diff --git a/cmd/runtime-checks.go b/cmd/runtime-checks.go deleted file mode 100644 index fc16e53e7..000000000 --- a/cmd/runtime-checks.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Minio Cloud Storage, (C) 2015, 2016 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 cmd - -import ( - "fmt" - "runtime" - - "github.com/hashicorp/go-version" - "github.com/minio/mc/pkg/console" -) - -// check if minimum Go version is met. -func checkGoVersion() { - // Current version. - curVersion, e := version.NewVersion(runtime.Version()[2:]) - if e != nil { - console.Fatalln("Unable to determine current go version.", e) - } - - // Prepare version constraint. - constraints, e := version.NewConstraint(minGoVersion) - if e != nil { - console.Fatalln("Unable to check go version.") - } - - // Check for minimum version. - if !constraints.Check(curVersion) { - console.Fatalln(fmt.Sprintf("Please recompile Minio with Golang version %s.", minGoVersion)) - } -} diff --git a/main.go b/main.go index 7c635a6b7..43d2a73ed 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ /* - * Minio Cloud Storage, (C) 2016 Minio, Inc. + * Minio Cloud Storage, (C) 2016,2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,11 +23,47 @@ package main // import "github.com/minio/minio" import ( + "fmt" "os" + "runtime" + version "github.com/hashicorp/go-version" + "github.com/minio/mc/pkg/console" minio "github.com/minio/minio/cmd" ) +const ( + // Minio requires at least Go v1.7 + minGoVersion = "1.7" + goVersionConstraint = ">= " + minGoVersion +) + +// Check if this binary is compiled with at least minimum Go version. +func checkGoVersion(goVersionStr string) error { + constraint, err := version.NewConstraint(goVersionConstraint) + if err != nil { + return fmt.Errorf("'%s': %s", goVersionConstraint, err) + } + + goVersion, err := version.NewVersion(goVersionStr) + if err != nil { + return err + } + + if !constraint.Check(goVersion) { + return fmt.Errorf("Minio is not compiled by Go %s. Please recompile accordingly.", + goVersionConstraint) + } + + return nil +} + func main() { + // When `go get` is used minimum Go version check is not triggered but it would have compiled it successfully. + // However such binary will fail at runtime, hence we also check Go version at runtime. + if err := checkGoVersion(runtime.Version()[2:]); err != nil { + console.Fatalln("Go runtime version check failed.", err) + } + minio.Main(os.Args, os.Exit) } diff --git a/main_test.go b/main_test.go new file mode 100644 index 000000000..85b9b2e8e --- /dev/null +++ b/main_test.go @@ -0,0 +1,50 @@ +/* + * Minio Cloud Storage, (C) 2017 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 ( + "fmt" + "testing" +) + +func TestCheckGoVersion(t *testing.T) { + // Test success cases. + testCases := []struct { + version string + expectedErr error + }{ + {minGoVersion, nil}, + {minGoVersion + ".10", nil}, + {"1.6.8", fmt.Errorf("Minio is not compiled by Go >= 1.7. Please recompile accordingly.")}, + {"0.1", fmt.Errorf("Minio is not compiled by Go >= 1.7. Please recompile accordingly.")}, + {".1", fmt.Errorf("Malformed version: .1")}, + {"somejunk", fmt.Errorf("Malformed version: somejunk")}, + } + + for _, testCase := range testCases { + err := checkGoVersion(testCase.version) + if testCase.expectedErr == nil { + if err != nil { + t.Fatalf("expected: %v, got: %v", testCase.expectedErr, err) + } + } else if err == nil { + t.Fatalf("expected: %v, got: %v", testCase.expectedErr, err) + } else if testCase.expectedErr.Error() != err.Error() { + t.Fatalf("expected: %v, got: %v", testCase.expectedErr, err) + } + } +} From 22909c849e8fbdc79ed6f766b6ebf40a2e4b4239 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 11 Feb 2017 17:17:58 -0800 Subject: [PATCH 66/75] objcache: Return io.ReaderAt to avoid Seeking and Reading. (#3735) --- cmd/xl-v1-object.go | 19 +++++++++++-------- pkg/objcache/objcache.go | 2 +- pkg/objcache/objcache_test.go | 4 ++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cmd/xl-v1-object.go b/cmd/xl-v1-object.go index 134af0a43..1ac3f23fe 100644 --- a/cmd/xl-v1-object.go +++ b/cmd/xl-v1-object.go @@ -202,19 +202,22 @@ func (xl xlObjects) GetObject(bucket, object string, startOffset int64, length i // Object cache enabled block. if xlMeta.Stat.Size > 0 && xl.objCacheEnabled { // Validate if we have previous cache. - var cachedBuffer io.ReadSeeker + var cachedBuffer io.ReaderAt cachedBuffer, err = xl.objCache.Open(path.Join(bucket, object), modTime) - if err == nil { // Cache hit. - // Advance the buffer to offset as if it was read. - if _, err = cachedBuffer.Seek(startOffset, 0); err != nil { // Seek to the offset. - return traceError(err) - } - // Write the requested length. - if _, err = io.CopyN(writer, cachedBuffer, length); err != nil { + if err == nil { // Cache hit + // Create a new section reader, starting at an offset with length. + reader := io.NewSectionReader(cachedBuffer, startOffset, length) + + // Copy the data out. + if _, err = io.Copy(writer, reader); err != nil { return traceError(err) } + + // Success. return nil + } // Cache miss. + // For unknown error, return and error out. if err != objcache.ErrKeyNotFoundInCache { return traceError(err) diff --git a/pkg/objcache/objcache.go b/pkg/objcache/objcache.go index 3a63a68de..d07a86214 100644 --- a/pkg/objcache/objcache.go +++ b/pkg/objcache/objcache.go @@ -217,7 +217,7 @@ func (c *Cache) Create(key string, size int64) (w io.WriteCloser, err error) { // returns an error ErrNotFoundInCache, if the key does not exist. // Returns ErrKeyNotFoundInCache if entry's lastAccessedTime is older // than objModTime. -func (c *Cache) Open(key string, objModTime time.Time) (io.ReadSeeker, error) { +func (c *Cache) Open(key string, objModTime time.Time) (io.ReaderAt, error) { // Entry exists, return the readable buffer. c.mutex.Lock() defer c.mutex.Unlock() diff --git a/pkg/objcache/objcache_test.go b/pkg/objcache/objcache_test.go index f1eed32d3..25cd1c69a 100644 --- a/pkg/objcache/objcache_test.go +++ b/pkg/objcache/objcache_test.go @@ -20,7 +20,6 @@ package objcache import ( "bytes" "io" - "io/ioutil" "testing" "time" ) @@ -173,7 +172,8 @@ func TestObjCache(t *testing.T) { t.Errorf("Test case 4 expected to pass, failed instead %s", err) } // Reads everything stored for key "test". - cbytes, err := ioutil.ReadAll(r) + cbytes := make([]byte, 5) + _, err = r.ReadAt(cbytes, 0) if err != nil { t.Errorf("Test case 4 expected to pass, failed instead %s", err) } From a53b909fcd9c868b86ded12065ee19cf3b0af8a3 Mon Sep 17 00:00:00 2001 From: Bala FA Date: Mon, 13 Feb 2017 13:54:34 +0530 Subject: [PATCH 67/75] mainVersion: Remove minio init and quiet handling (#3739) --- cmd/version-main.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/cmd/version-main.go b/cmd/version-main.go index 9ed543842..80370332a 100644 --- a/cmd/version-main.go +++ b/cmd/version-main.go @@ -1,5 +1,5 @@ /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2015, 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,12 @@ var versionCmd = cli.Command{ Name: "version", Usage: "Print version.", Action: mainVersion, - Flags: globalFlags, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "help, h", + Usage: "Show this help.", + }, + }, CustomHelpTemplate: `NAME: minio {{.Name}} - {{.Usage}} @@ -35,8 +40,8 @@ USAGE: FLAGS: {{range .Flags}}{{.}} {{end}} - -`, +VERSION: + ` + Version + `{{"\n"}}`, } func mainVersion(ctx *cli.Context) { @@ -44,13 +49,6 @@ func mainVersion(ctx *cli.Context) { cli.ShowCommandHelpAndExit(ctx, "version", 1) } - // Initialization routine, such as config loading, enable logging, .. - minioInit(ctx) - - if globalQuiet { - return - } - console.Println("Version: " + Version) console.Println("Release-Tag: " + ReleaseTag) console.Println("Commit-ID: " + CommitID) From c6e76160ad72f5c3b9cd359e92721a9bc7b69c91 Mon Sep 17 00:00:00 2001 From: Dee Koder Date: Tue, 14 Feb 2017 14:20:29 -0800 Subject: [PATCH 68/75] Update README.md --- docs/tls/README.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docs/tls/README.md b/docs/tls/README.md index 57f2ff8c1..3025c161f 100644 --- a/docs/tls/README.md +++ b/docs/tls/README.md @@ -23,9 +23,7 @@ You need to download [generate_cert.go](https://golang.org/src/crypto/tls/genera `generate_cert.go` already provides SAN certificates with DNS and IP entries: ```sh - go run generate_cert.go -ca --host "10.10.0.3" - ``` #### With OpenSSL: @@ -33,17 +31,13 @@ go run generate_cert.go -ca --host "10.10.0.3" Generate the private key: ```sh - openssl genrsa -out private.key 1024 - ``` Generate the self-signed certificate: ```sh - openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=country/ST=state/L=location/O=organization/CN=domain" - ``` ### Windows @@ -57,9 +51,7 @@ Download and decompress the Windows version of GnuTLS from [here](http://www.gnu Make sure to add extracted GnuTLS binary path to your system path. ``` - setx path "%path%;C:\Users\MyUser\Downloads\gnutls-3.4.9-w64\bin" - ``` You may need to restart your powershell console for this to take affect. @@ -69,9 +61,7 @@ You may need to restart your powershell console for this to take affect. Run the following command to create `private.key` ``` - certtool.exe --generate-privkey --outfile private.key - ``` #### Generate public.crt @@ -121,9 +111,7 @@ encryption_key Generate public certificate ``` - certtool.exe --generate-self-signed --load-privkey private.key --template cert.cnf --outfile public.crt - ``` ## 3. Configure Minio with the generated certificate From 602dac87730656580c5645215a771ea3b41426a5 Mon Sep 17 00:00:00 2001 From: Bala FA Date: Wed, 15 Feb 2017 14:01:00 +0530 Subject: [PATCH 69/75] mainUpdate: refactor to handle quiet flag properly (#3744) --- cmd/main.go | 9 +- cmd/update-main.go | 406 +++++++++++++++----------------- cmd/update-main_nix_test.go | 109 --------- cmd/update-main_test.go | 275 +++++++++++++++++++++ cmd/update-main_windows_test.go | 109 --------- cmd/update-notifier_test.go | 9 +- 6 files changed, 479 insertions(+), 438 deletions(-) delete mode 100644 cmd/update-main_nix_test.go create mode 100644 cmd/update-main_test.go delete mode 100644 cmd/update-main_windows_test.go diff --git a/cmd/main.go b/cmd/main.go index 31d2d8047..994e77d80 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -145,14 +145,13 @@ func checkMainSyntax(c *cli.Context) { func checkUpdate() { // Do not print update messages, if quiet flag is set. if !globalQuiet { - updateMsg, _, err := getReleaseUpdate(minioUpdateStableURL, 1*time.Second) + older, downloadURL, err := getUpdateInfo(1 * time.Second) if err != nil { - // Ignore any errors during getReleaseUpdate(), possibly - // because of network errors. + // Its OK to ignore any errors during getUpdateInfo() here. return } - if updateMsg.Update { - console.Println(updateMsg) + if older > time.Duration(0) { + console.Println(colorizeUpdateMessage(downloadURL, older)) } } } diff --git a/cmd/update-main.go b/cmd/update-main.go index b301c1520..4198506d3 100644 --- a/cmd/update-main.go +++ b/cmd/update-main.go @@ -1,5 +1,5 @@ /* - * Minio Cloud Storage, (C) 2015 Minio, Inc. + * Minio Cloud Storage, (C) 2015, 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package cmd import ( "bytes" - "errors" + "fmt" "io/ioutil" "net/http" "os" @@ -36,7 +36,16 @@ var updateCmd = cli.Command{ Name: "update", Usage: "Check for a new software update.", Action: mainUpdate, - Flags: globalFlags, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "help, h", + Usage: "Show this help.", + }, + cli.BoolFlag{ + Name: "quiet", + Usage: "Disable any update messages.", + }, + }, CustomHelpTemplate: `Name: minio {{.Name}} - {{.Usage}} @@ -46,238 +55,215 @@ USAGE: FLAGS: {{range .Flags}}{{.}} {{end}} -EXAMPLES: - 1. Check for any new official release. - $ minio {{.Name}} -`, +EXIT STATUS: + 0 - You are already running the most recent version. + 1 - New update is available. + -1 - Error in getting update information. + +VERSION: + ` + Version + `{{"\n"}}`, } -// update URL endpoints. -const ( - minioUpdateStableURL = "https://dl.minio.io/server/minio/release" -) +const releaseTagTimeLayout = "2006-01-02T15-04-05Z" -// updateMessage container to hold update messages. -type updateMessage struct { - Update bool `json:"update"` - Download string `json:"downloadURL"` - NewerThan time.Duration `json:"newerThan"` -} +const minioReleaseURL = "https://dl.minio.io/server/minio/release/" + runtime.GOOS + "-" + runtime.GOARCH + "/" -// String colorized update message. -func (u updateMessage) String() string { - if !u.Update { - updateMessage := color.New(color.FgGreen, color.Bold).SprintfFunc() - return updateMessage("You are already running the most recent version of ‘minio’.") +func getCurrentReleaseTime(minioVersion, minioBinaryPath string) (releaseTime time.Time, err error) { + if releaseTime, err = time.Parse(time.RFC3339, minioVersion); err == nil { + return releaseTime, err } - msg := colorizeUpdateMessage(u.Download, u.NewerThan) - return msg -} -func parseReleaseData(data string) (time.Time, error) { - releaseStr := strings.Fields(data) - if len(releaseStr) < 2 { - return time.Time{}, errors.New("Update data malformed") - } - releaseDate := releaseStr[1] - releaseDateSplits := strings.SplitN(releaseDate, ".", 3) - if len(releaseDateSplits) < 3 { - return time.Time{}, (errors.New("Update data malformed")) - } - if releaseDateSplits[0] != globalMinioDefaultOwnerID { - return time.Time{}, (errors.New("Update data malformed, missing minio tag")) - } - // "OFFICIAL" tag is still kept for backward compatibility. - // We should remove this for the next release. - if releaseDateSplits[1] != "RELEASE" && releaseDateSplits[1] != "OFFICIAL" { - return time.Time{}, (errors.New("Update data malformed, missing RELEASE tag")) - } - dateSplits := strings.SplitN(releaseDateSplits[2], "T", 2) - if len(dateSplits) < 2 { - return time.Time{}, (errors.New("Update data malformed, not in modified RFC3359 form")) - } - dateSplits[1] = strings.Replace(dateSplits[1], "-", ":", -1) - date := strings.Join(dateSplits, "T") - - parsedDate, err := time.Parse(time.RFC3339, date) + // Looks like version is minio non-standard, we use minio binary's ModTime as release time. + fi, err := os.Stat(minioBinaryPath) if err != nil { - return time.Time{}, err - } - return parsedDate, nil -} - -// User Agent should always following the below style. -// Please open an issue to discuss any new changes here. -// -// Minio (OS; ARCH) APP/VER APP/VER -var ( - userAgentSuffix = "Minio/" + Version + " " + "Minio/" + ReleaseTag + " " + "Minio/" + CommitID -) - -// Check if the operating system is a docker container. -func isDocker() bool { - cgroup, err := ioutil.ReadFile("/proc/self/cgroup") - if err != nil && !os.IsNotExist(err) { - errorIf(err, "Unable to read `cgroup` file.") - } - - return bytes.Contains(cgroup, []byte("docker")) -} - -// Check if the minio server binary was built with source. -func isSourceBuild() bool { - return Version == goGetTag -} - -// Fetch the current version of the Minio server binary. -func getCurrentMinioVersion() (current time.Time, err error) { - // For development builds we check for binary modTime - // to validate against latest minio server release. - if Version != goGetTag { - // Parse current minio version into RFC3339. - current, err = time.Parse(time.RFC3339, Version) - if err != nil { - return time.Time{}, err - } - return current, nil - } // else { - // For all development builds through `go get`. - // fall back to looking for version of the build - // date of the binary itself. - var fi os.FileInfo - fi, err = os.Stat(os.Args[0]) - if err != nil { - return time.Time{}, err - } - return fi.ModTime(), nil -} - -// verify updates for releases. -func getReleaseUpdate(updateURL string, duration time.Duration) (updateMsg updateMessage, errMsg string, err error) { - // Construct a new update url. - newUpdateURLPrefix := updateURL + "/" + runtime.GOOS + "-" + runtime.GOARCH - newUpdateURL := newUpdateURLPrefix + "/minio.shasum" - - // Get the downloadURL. - var downloadURL string - if isDocker() { - downloadURL = "docker pull minio/minio" + err = fmt.Errorf("Unable to get ModTime of %s. %s", minioBinaryPath, err) } else { - switch runtime.GOOS { - case globalWindowsOSName: - // For windows. - downloadURL = newUpdateURLPrefix + "/minio.exe" - default: - // For all other operating systems. - downloadURL = newUpdateURLPrefix + "/minio" - } + releaseTime = fi.ModTime().UTC() } - // Initialize update message. - updateMsg = updateMessage{ - Download: downloadURL, + return releaseTime, err +} + +// GetCurrentReleaseTime - returns this process's release time. If it is official minio version, +// parsed version is returned else minio binary's mod time is returned. +func GetCurrentReleaseTime() (releaseTime time.Time, err error) { + return getCurrentReleaseTime(Version, os.Args[0]) +} + +func isDocker(cgroupFile string) (bool, error) { + cgroup, err := ioutil.ReadFile(cgroupFile) + if os.IsNotExist(err) { + err = nil } - // Instantiate a new client with 3 sec timeout. + return bytes.Contains(cgroup, []byte("docker")), err +} + +// IsDocker - returns if the environment is docker or not. +func IsDocker() bool { + found, err := isDocker("/proc/self/cgroup") + if err != nil { + console.Fatalf("Error in docker check: %s", err) + } + + return found +} + +func isSourceBuild(minioVersion string) bool { + _, err := time.Parse(time.RFC3339, minioVersion) + return err != nil +} + +// IsSourceBuild - returns if this binary is made from source or not. +func IsSourceBuild() bool { + return isSourceBuild(Version) +} + +// DO NOT CHANGE USER AGENT STYLE. +// The style should be +// Minio (; [; docker][; source]) Minio/ Minio/ Minio/ +// +// For any change here should be discussed by openning an issue at https://github.com/minio/minio/issues. +func getUserAgent() string { + userAgent := "Minio (" + runtime.GOOS + "; " + runtime.GOARCH + if IsDocker() { + userAgent += "; docker" + } + if IsSourceBuild() { + userAgent += "; source" + } + userAgent += ") " + " Minio/" + Version + " Minio/" + ReleaseTag + " Minio/" + CommitID + + return userAgent +} + +func downloadReleaseData(releaseChecksumURL string, timeout time.Duration) (data string, err error) { + req, err := http.NewRequest("GET", releaseChecksumURL, nil) + if err != nil { + return data, err + } + req.Header.Set("User-Agent", getUserAgent()) + client := &http.Client{ - Timeout: duration, + Timeout: timeout, } - current, err := getCurrentMinioVersion() - if err != nil { - errMsg = "Unable to fetch the current version of Minio server." - return - } - - // Initialize new request. - req, err := http.NewRequest("GET", newUpdateURL, nil) - if err != nil { - return - } - - userAgentPrefix := func() string { - prefix := "Minio (" + runtime.GOOS + "; " + runtime.GOARCH - // if its a source build. - if isSourceBuild() { - if isDocker() { - prefix = prefix + "; " + "docker; source) " - } else { - prefix = prefix + "; " + "source) " - } - return prefix - } // else { not source. - if isDocker() { - prefix = prefix + "; " + "docker) " - } else { - prefix = prefix + ") " - } - return prefix - }() - - // Set user agent. - req.Header.Set("User-Agent", userAgentPrefix+" "+userAgentSuffix) - - // Fetch new update. resp, err := client.Do(req) if err != nil { - return + return data, err + } + if resp == nil { + return data, fmt.Errorf("No response from server to download URL %s", releaseChecksumURL) } - // Verify if we have a valid http response i.e http.StatusOK. - if resp != nil { - if resp.StatusCode != http.StatusOK { - errMsg = "Failed to retrieve update notice." - err = errors.New("http status : " + resp.Status) - return + if resp.StatusCode != http.StatusOK { + return data, fmt.Errorf("Error downloading URL %s. Response: %v", releaseChecksumURL, resp.Status) + } + + dataBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return data, fmt.Errorf("Error reading response. %s", err) + } + + data = string(dataBytes) + return data, err +} + +// DownloadReleaseData - downloads release data from minio official server. +func DownloadReleaseData(timeout time.Duration) (data string, err error) { + return downloadReleaseData(minioReleaseURL+"minio.shasum", timeout) +} + +func parseReleaseData(data string) (releaseTime time.Time, err error) { + fields := strings.Fields(data) + if len(fields) != 2 { + err = fmt.Errorf("Unknown release data `%s`", data) + return releaseTime, err + } + + releaseInfo := fields[1] + if fields = strings.Split(releaseInfo, "."); len(fields) != 3 { + err = fmt.Errorf("Unknown release information `%s`", releaseInfo) + return releaseTime, err + } + + if !(fields[0] == "minio" && fields[1] == "RELEASE") { + err = fmt.Errorf("Unknown release '%s'", releaseInfo) + return releaseTime, err + } + + releaseTime, err = time.Parse(releaseTagTimeLayout, fields[2]) + if err != nil { + err = fmt.Errorf("Unknown release time format. %s", err) + } + + return releaseTime, err +} + +func getLatestReleaseTime(timeout time.Duration) (releaseTime time.Time, err error) { + data, err := DownloadReleaseData(timeout) + if err != nil { + return releaseTime, err + } + + return parseReleaseData(data) +} + +func getDownloadURL() (downloadURL string) { + if IsDocker() { + return "docker pull minio/minio" + } + + if runtime.GOOS == "windows" { + return minioReleaseURL + "minio.exe" + } + + return minioReleaseURL + "minio" +} + +func getUpdateInfo(timeout time.Duration) (older time.Duration, downloadURL string, err error) { + currentReleaseTime, err := GetCurrentReleaseTime() + if err != nil { + return older, downloadURL, err + } + + latestReleaseTime, err := getLatestReleaseTime(timeout) + if err != nil { + return older, downloadURL, err + } + + if latestReleaseTime.After(currentReleaseTime) { + older = latestReleaseTime.Sub(currentReleaseTime) + downloadURL = getDownloadURL() + } + + return older, downloadURL, nil +} + +func mainUpdate(ctx *cli.Context) { + if len(ctx.Args()) != 0 { + cli.ShowCommandHelpAndExit(ctx, "update", -1) + } + + quiet := ctx.Bool("quiet") || ctx.GlobalBool("quiet") + quietPrintln := func(args ...interface{}) { + if !quiet { + console.Println(args...) } } - // Read the response body. - updateBody, err := ioutil.ReadAll(resp.Body) + older, downloadURL, err := getUpdateInfo(10 * time.Second) if err != nil { - errMsg = "Failed to retrieve update notice. Please try again later." - return + quietPrintln(err) + os.Exit(-1) } - errMsg = "Failed to retrieve update notice. Please try again later. Please report this issue at https://github.com/minio/minio/issues" - - // Parse the date if its valid. - latest, err := parseReleaseData(string(updateBody)) - if err != nil { - return + if older != time.Duration(0) { + quietPrintln(colorizeUpdateMessage(downloadURL, older)) + os.Exit(1) } - // Verify if the date is not zero. - if latest.IsZero() { - err = errors.New("Release date cannot be zero. Please report this issue at https://github.com/minio/minio/issues") - return - } - - // Is the update latest?. - if latest.After(current) { - updateMsg.Update = true - updateMsg.NewerThan = latest.Sub(current) - } - - // Return update message. - return updateMsg, "", nil -} - -// main entry point for update command. -func mainUpdate(ctx *cli.Context) { - // Initialization routine, such as config loading, enable logging, .. - minioInit(ctx) - - if globalQuiet { - return - } - - // Check for update. - var updateMsg updateMessage - var errMsg string - var err error - var secs = time.Second * 3 - updateMsg, errMsg, err = getReleaseUpdate(minioUpdateStableURL, secs) - fatalIf(err, errMsg) - console.Println(updateMsg) + colorSprintf := color.New(color.FgGreen, color.Bold).SprintfFunc() + quietPrintln(colorSprintf("You are already running the most recent version of ‘minio’.")) + os.Exit(0) } diff --git a/cmd/update-main_nix_test.go b/cmd/update-main_nix_test.go deleted file mode 100644 index 11e1a0b77..000000000 --- a/cmd/update-main_nix_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// +build linux darwin dragonfly freebsd netbsd openbsd - -/* - * Minio Cloud Storage, (C) 2016 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 cmd - -import ( - "fmt" - "net/http" - "net/http/httptest" - "reflect" - "runtime" - "testing" - "time" -) - -// Validate when release versions are properly set. -func TestReleaseUpdateVersion(t *testing.T) { - Version = "2016-10-06T00:08:32Z" - ReleaseTag = "RELEASE.2016-10-06T00-08-32Z" - CommitID = "d1c38ba8f0b3aecdf9b932c087dd65c21eebac33" - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z") - })) - userAgentSuffix = "Minio/" + Version + " " + "Minio/" + ReleaseTag + " " + "Minio/" + CommitID - defer ts.Close() - testCases := []struct { - updateURL string - updateMsg updateMessage - errMsg string - shouldPass bool - }{ - { - updateURL: ts.URL, - updateMsg: updateMessage{ - Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio", - Update: true, - NewerThan: 90487000000000, - }, - errMsg: "", - shouldPass: true, - }, - } - - // Validates all the errors reported. - for i, testCase := range testCases { - updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1) - if testCase.shouldPass && err != nil { - t.Errorf("Test %d: Unable to fetch release update %s", i+1, err) - } - if errMsg != testCase.errMsg { - t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg) - } - if !reflect.DeepEqual(updateMsg, testCase.updateMsg) { - t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg) - } - } -} - -func TestReleaseUpdate(t *testing.T) { - Version = "DEVELOPMENT.GOGET" - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "Hello, client") - })) - defer ts.Close() - testCases := []struct { - updateURL string - updateMsg updateMessage - errMsg string - shouldPass bool - }{ - { - updateURL: ts.URL, - updateMsg: updateMessage{ - Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio", - }, - errMsg: "Failed to retrieve update notice. Please try again later. Please report this issue at https://github.com/minio/minio/issues", - shouldPass: false, - }, - } - - // Validates all the errors reported. - for i, testCase := range testCases { - updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1) - if testCase.shouldPass && err != nil { - t.Errorf("Test %d: Unable to fetch release update %s", i+1, err) - } - if errMsg != testCase.errMsg { - t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg) - } - if !reflect.DeepEqual(updateMsg, testCase.updateMsg) { - t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg) - } - } -} diff --git a/cmd/update-main_test.go b/cmd/update-main_test.go new file mode 100644 index 000000000..364e698c5 --- /dev/null +++ b/cmd/update-main_test.go @@ -0,0 +1,275 @@ +/* + * Minio Cloud Storage, (C) 2017 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 cmd + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "runtime" + "testing" + "time" +) + +func TestGetCurrentReleaseTime(t *testing.T) { + minioVersion1 := time.Now().UTC().Format(time.RFC3339) + releaseTime1, _ := time.Parse(time.RFC3339, minioVersion1) + + minioVersion2 := "DEVELOPMENT.GOGET" + tmpfile, err := ioutil.TempFile("", "get-current-release-time-testcase") + if err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + defer os.Remove(tmpfile.Name()) + minioBinaryPath2 := tmpfile.Name() + fi, err := tmpfile.Stat() + if err != nil { + t.Fatalf("Unable to get temporary file info. %s", err) + } + if err = tmpfile.Close(); err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + releaseTime2 := fi.ModTime().UTC() + + errorMessage1 := "Unable to get ModTime of . stat : no such file or directory" + if runtime.GOOS == "windows" { + errorMessage1 = "Unable to get ModTime of . Lstat : The system cannot find the path specified." + } + + errorMessage2 := "Unable to get ModTime of non-existing-file. stat non-existing-file: no such file or directory" + if runtime.GOOS == "windows" { + errorMessage2 = "Unable to get ModTime of non-existing-file. GetFileAttributesEx non-existing-file: The system cannot find the file specified." + } + + testCases := []struct { + minioVersion string + minioBinaryPath string + expectedResult time.Time + expectedErr error + }{ + {minioVersion1, "", releaseTime1, nil}, + {minioVersion1, minioBinaryPath2, releaseTime1, nil}, + {minioVersion2, minioBinaryPath2, releaseTime2, nil}, + {"junk", minioBinaryPath2, releaseTime2, nil}, + {"3.2.0", minioBinaryPath2, releaseTime2, nil}, + {minioVersion2, "", time.Time{}, fmt.Errorf(errorMessage1)}, + {"junk", "non-existing-file", time.Time{}, fmt.Errorf(errorMessage2)}, + {"3.2.0", "non-existing-file", time.Time{}, fmt.Errorf(errorMessage2)}, + } + + if runtime.GOOS == "linux" { + testCases = append(testCases, struct { + minioVersion string + minioBinaryPath string + expectedResult time.Time + expectedErr error + }{"3.2a", "/proc/1/cwd", time.Time{}, fmt.Errorf("Unable to get ModTime of /proc/1/cwd. stat /proc/1/cwd: permission denied")}) + } + + for _, testCase := range testCases { + result, err := getCurrentReleaseTime(testCase.minioVersion, testCase.minioBinaryPath) + if testCase.expectedErr == nil { + if err != nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + } else if err == nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } else if testCase.expectedErr.Error() != err.Error() { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + + if !testCase.expectedResult.Equal(result) { + t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result) + } + } +} + +func TestIsDocker(t *testing.T) { + createTempFile := func(content string) string { + tmpfile, err := ioutil.TempFile("", "isdocker-testcase") + if err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + if _, err = tmpfile.Write([]byte(content)); err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + if err = tmpfile.Close(); err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + return tmpfile.Name() + } + + filename1 := createTempFile(`11:pids:/user.slice/user-1000.slice/user@1000.service +10:blkio:/ +9:hugetlb:/ +8:perf_event:/ +7:cpuset:/ +6:devices:/user.slice +5:net_cls,net_prio:/ +4:cpu,cpuacct:/ +3:memory:/user/bala/0 +2:freezer:/user/bala/0 +1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service +`) + defer os.Remove(filename1) + filename2 := createTempFile(`14:name=systemd:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +13:pids:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +12:hugetlb:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +11:net_prio:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +10:perf_event:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +9:net_cls:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +8:freezer:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +7:devices:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +6:memory:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +5:blkio:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +4:cpuacct:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +3:cpu:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +2:cpuset:/docker/d5eb950884d828237f60f624ff575a1a7a4daa28a8d4d750040527ed9545e727 +1:name=openrc:/docker +`) + defer os.Remove(filename2) + + testCases := []struct { + filename string + expectedResult bool + expectedErr error + }{ + {"", false, nil}, + {"/tmp/non-existing-file", false, nil}, + {filename1, false, nil}, + {filename2, true, nil}, + } + + if runtime.GOOS == "linux" { + testCases = append(testCases, struct { + filename string + expectedResult bool + expectedErr error + }{"/proc/1/cwd", false, fmt.Errorf("open /proc/1/cwd: permission denied")}) + } + + for _, testCase := range testCases { + result, err := isDocker(testCase.filename) + if testCase.expectedErr == nil { + if err != nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + } else if err == nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } else if testCase.expectedErr.Error() != err.Error() { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + + if testCase.expectedResult != result { + t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result) + } + } +} + +func TestIsSourceBuild(t *testing.T) { + testCases := []struct { + minioVersion string + expectedResult bool + }{ + {time.Now().UTC().Format(time.RFC3339), false}, + {"DEVELOPMENT.GOGET", true}, + {"junk", true}, + {"3.2.4", true}, + } + + for _, testCase := range testCases { + result := isSourceBuild(testCase.minioVersion) + if testCase.expectedResult != result { + t.Fatalf("expected: %v, got: %v", testCase.expectedResult, result) + } + } +} + +func TestDownloadReleaseData(t *testing.T) { + httpServer1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + defer httpServer1.Close() + httpServer2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z") + })) + defer httpServer2.Close() + httpServer3 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "", http.StatusNotFound) + })) + defer httpServer3.Close() + + testCases := []struct { + releaseChecksumURL string + expectedResult string + expectedErr error + }{ + {httpServer1.URL, "", nil}, + {httpServer2.URL, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z\n", nil}, + {httpServer3.URL, "", fmt.Errorf("Error downloading URL " + httpServer3.URL + ". Response: 404 Not Found")}, + } + + for _, testCase := range testCases { + result, err := downloadReleaseData(testCase.releaseChecksumURL, 1*time.Second) + if testCase.expectedErr == nil { + if err != nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + } else if err == nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } else if testCase.expectedErr.Error() != err.Error() { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + + if testCase.expectedResult != result { + t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result) + } + } +} + +func TestParseReleaseData(t *testing.T) { + releaseTime, _ := time.Parse(releaseTagTimeLayout, "2016-10-07T01-16-39Z") + testCases := []struct { + data string + expectedResult time.Time + expectedErr error + }{ + {"more than two fields", time.Time{}, fmt.Errorf("Unknown release data `more than two fields`")}, + {"more than", time.Time{}, fmt.Errorf("Unknown release information `than`")}, + {"more than.two.fields", time.Time{}, fmt.Errorf("Unknown release 'than.two.fields'")}, + {"more minio.RELEASE.fields", time.Time{}, fmt.Errorf(`Unknown release time format. parsing time "fields" as "2006-01-02T15-04-05Z": cannot parse "fields" as "2006"`)}, + {"more minio.RELEASE.2016-10-07T01-16-39Z", releaseTime, nil}, + {"fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z\n", releaseTime, nil}, + } + + for _, testCase := range testCases { + result, err := parseReleaseData(testCase.data) + if testCase.expectedErr == nil { + if err != nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + } else if err == nil { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } else if testCase.expectedErr.Error() != err.Error() { + t.Fatalf("error: expected: %v, got: %v", testCase.expectedErr, err) + } + + if !testCase.expectedResult.Equal(result) { + t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result) + } + } +} diff --git a/cmd/update-main_windows_test.go b/cmd/update-main_windows_test.go deleted file mode 100644 index 9900be556..000000000 --- a/cmd/update-main_windows_test.go +++ /dev/null @@ -1,109 +0,0 @@ -// +build windows - -/* - * Minio Cloud Storage, (C) 2016 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 cmd - -import ( - "fmt" - "net/http" - "net/http/httptest" - "reflect" - "runtime" - "testing" - "time" -) - -// Validate when release versions are properly set. -func TestReleaseUpdateVersion(t *testing.T) { - Version = "2016-10-06T00:08:32Z" - ReleaseTag = "RELEASE.2016-10-06T00-08-32Z" - CommitID = "d1c38ba8f0b3aecdf9b932c087dd65c21eebac33" - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "fbe246edbd382902db9a4035df7dce8cb441357d minio.RELEASE.2016-10-07T01-16-39Z") - })) - userAgentSuffix = "Minio/" + Version + " " + "Minio/" + ReleaseTag + " " + "Minio/" + CommitID - defer ts.Close() - testCases := []struct { - updateURL string - updateMsg updateMessage - errMsg string - shouldPass bool - }{ - { - updateURL: ts.URL, - updateMsg: updateMessage{ - Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio.exe", - Update: true, - NewerThan: 90487000000000, - }, - errMsg: "", - shouldPass: true, - }, - } - - // Validates all the errors reported. - for i, testCase := range testCases { - updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1) - if testCase.shouldPass && err != nil { - t.Errorf("Test %d: Unable to fetch release update %s", i+1, err) - } - if errMsg != testCase.errMsg { - t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg) - } - if !reflect.DeepEqual(updateMsg, testCase.updateMsg) { - t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg) - } - } -} - -func TestReleaseUpdate(t *testing.T) { - Version = "DEVELOPMENT.GOGET" - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "Hello, client") - })) - defer ts.Close() - testCases := []struct { - updateURL string - updateMsg updateMessage - errMsg string - shouldPass bool - }{ - { - updateURL: ts.URL, - updateMsg: updateMessage{ - Download: ts.URL + "/" + runtime.GOOS + "-" + runtime.GOARCH + "/minio.exe", - }, - errMsg: "Failed to retrieve update notice. Please try again later. Please report this issue at https://github.com/minio/minio/issues", - shouldPass: false, - }, - } - - // Validates all the errors reported. - for i, testCase := range testCases { - updateMsg, errMsg, err := getReleaseUpdate(testCase.updateURL, time.Second*1) - if testCase.shouldPass && err != nil { - t.Errorf("Test %d: Unable to fetch release update %s", i+1, err) - } - if errMsg != testCase.errMsg { - t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.errMsg, errMsg) - } - if !reflect.DeepEqual(updateMsg, testCase.updateMsg) { - t.Errorf("Test %d: Expected %#v, got %#v", i+1, testCase.updateMsg, updateMsg) - } - } -} diff --git a/cmd/update-notifier_test.go b/cmd/update-notifier_test.go index b6c83e567..ff6a6408d 100644 --- a/cmd/update-notifier_test.go +++ b/cmd/update-notifier_test.go @@ -24,12 +24,11 @@ import ( // Tests update notifier string builder. func TestUpdateNotifier(t *testing.T) { - updateMsg := minioUpdateStableURL - colorUpdateMsg := colorizeUpdateMessage(updateMsg, time.Duration(72*time.Hour)) - if strings.Index(colorUpdateMsg, "minutes") == -1 { + colorUpdateMsg := colorizeUpdateMessage(minioReleaseURL, time.Duration(72*time.Hour)) + if !strings.Contains(colorUpdateMsg, "minutes") { t.Fatal("Duration string not found in colorized update message", colorUpdateMsg) } - if strings.Index(colorUpdateMsg, updateMsg) == -1 { - t.Fatal("Update message not found in colorized update message", updateMsg) + if !strings.Contains(colorUpdateMsg, minioReleaseURL) { + t.Fatal("Update message not found in colorized update message", minioReleaseURL) } } From 13c3b9cbcb089bed1557bd5d82bd3f6dfa9817de Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 15 Feb 2017 02:25:38 -0800 Subject: [PATCH 70/75] main/cli: Don't print hidden flags/commands in help template. (#3748) Always use .VisibleFlags and .VisibleCommands to not print Hidden flags as expected from help template. --- cmd/main.go | 8 ++++---- cmd/server-main.go | 2 +- cmd/update-main.go | 2 +- cmd/version-main.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 994e77d80..f490d2582 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -53,13 +53,13 @@ DESCRIPTION: {{.Description}} USAGE: - minio {{if .Flags}}[flags] {{end}}command{{if .Flags}}{{end}} [arguments...] + minio {{if .VisibleFlags}}[flags] {{end}}command{{if .VisibleFlags}}{{end}} [arguments...] COMMANDS: - {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} - {{end}}{{if .Flags}} + {{range .VisibleCommands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} + {{end}}{{if .VisibleFlags}} FLAGS: - {{range .Flags}}{{.}} + {{range .VisibleFlags}}{{.}} {{end}}{{end}} VERSION: ` + Version + diff --git a/cmd/server-main.go b/cmd/server-main.go index 6b4deca7f..f48f90d07 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -52,7 +52,7 @@ USAGE: minio {{.Name}} [FLAGS] PATH [PATH...] FLAGS: - {{range .Flags}}{{.}} + {{range .VisibleFlags}}{{.}} {{end}} ENVIRONMENT VARIABLES: ACCESS: diff --git a/cmd/update-main.go b/cmd/update-main.go index 4198506d3..4876f9849 100644 --- a/cmd/update-main.go +++ b/cmd/update-main.go @@ -53,7 +53,7 @@ USAGE: minio {{.Name}} [FLAGS] FLAGS: - {{range .Flags}}{{.}} + {{range .VisibleFlags}}{{.}} {{end}} EXIT STATUS: 0 - You are already running the most recent version. diff --git a/cmd/version-main.go b/cmd/version-main.go index 80370332a..0ca92c52b 100644 --- a/cmd/version-main.go +++ b/cmd/version-main.go @@ -38,7 +38,7 @@ USAGE: minio {{.Name}} FLAGS: - {{range .Flags}}{{.}} + {{range .VisibleFlags}}{{.}} {{end}} VERSION: ` + Version + `{{"\n"}}`, From fb39c7c26b60b0fb8883b7a27747ce9192fb47bf Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 15 Feb 2017 03:47:47 -0800 Subject: [PATCH 71/75] sRPC/client: Properly trim storageRPCPath for actual disk path. (#3749) Never print internal RPC endpoint paths. --- cmd/storage-rpc-client.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cmd/storage-rpc-client.go b/cmd/storage-rpc-client.go index ebe62e35d..4020b6382 100644 --- a/cmd/storage-rpc-client.go +++ b/cmd/storage-rpc-client.go @@ -23,6 +23,7 @@ import ( "net/rpc" "net/url" "path" + "strings" "github.com/minio/minio/pkg/disk" ) @@ -132,20 +133,20 @@ func newStorageRPC(ep *url.URL) (StorageAPI, error) { // Stringer interface compatible representation of network device. func (n *networkStorage) String() string { - return n.rpcClient.ServerAddr() + ":" + n.rpcClient.ServiceEndpoint() + // Remove the storage RPC path prefix, internal paths are meaningless. + serviceEndpoint := strings.TrimPrefix(n.rpcClient.ServiceEndpoint(), storageRPCPath) + return n.rpcClient.ServerAddr() + ":" + serviceEndpoint } // Init - attempts a login to reconnect. func (n *networkStorage) Init() error { - err := n.rpcClient.Login() - return toStorageErr(err) + return toStorageErr(n.rpcClient.Login()) } // Closes the underlying RPC connection. -func (n *networkStorage) Close() (err error) { +func (n *networkStorage) Close() error { // Close the underlying connection. - err = n.rpcClient.Close() - return toStorageErr(err) + return toStorageErr(n.rpcClient.Close()) } // DiskInfo - fetch disk information for a remote disk. From 7f86a21317f8369324ecc447a0a0bf01b60fac3e Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 15 Feb 2017 19:45:45 +0100 Subject: [PATCH 72/75] admin: Add ServerInfo API() (#3743) --- cmd/admin-handlers.go | 92 +++++++++++++++++++++++++ cmd/admin-router.go | 3 + cmd/event-notifier.go | 17 ++++- cmd/server-startup-msg.go | 6 +- pkg/madmin/info-commands.go | 119 +++++++++++++++++++++++++++++++++ pkg/madmin/service-commands.go | 45 +------------ 6 files changed, 235 insertions(+), 47 deletions(-) create mode 100644 pkg/madmin/info-commands.go diff --git a/cmd/admin-handlers.go b/cmd/admin-handlers.go index 4a7bb547b..016db0a24 100644 --- a/cmd/admin-handlers.go +++ b/cmd/admin-handlers.go @@ -188,6 +188,98 @@ func (adminAPI adminAPIHandlers) ServiceCredentialsHandler(w http.ResponseWriter w.WriteHeader(http.StatusOK) } +// ServerProperties holds some server information such as, version, region +// uptime, etc.. +type ServerProperties struct { + Uptime time.Duration `json:"uptime"` + Version string `json:"version"` + CommitID string `json:"commitID"` + Region string `json:"region"` + SQSARN []string `json:"sqsARN"` +} + +// ServerConnStats holds transferred bytes from/to the server +type ServerConnStats struct { + TotalInputBytes uint64 `json:"transferred"` + TotalOutputBytes uint64 `json:"received"` + Throughput uint64 `json:"throughput,omitempty"` +} + +// ServerInfo holds the information that will be returned by ServerInfo API +type ServerInfo struct { + StorageInfo StorageInfo `json:"storage"` + ConnStats ServerConnStats `json:"network"` + Properties ServerProperties `json:"server"` +} + +// ServerInfoHandler - GET /?server-info +// ---------- +// Get server information +func (adminAPI adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Request) { + // Authenticate request + adminAPIErr := checkRequestAuthType(r, "", "", "") + if adminAPIErr != ErrNone { + writeErrorResponse(w, adminAPIErr, r.URL) + return + } + + // Build storage info + objLayer := newObjectLayerFn() + if objLayer == nil { + writeErrorResponse(w, ErrServerNotInitialized, r.URL) + return + } + storage := objLayer.StorageInfo() + + // Build list of enabled ARNs queues + var arns []string + for queueArn := range globalEventNotifier.GetAllExternalTargets() { + arns = append(arns, queueArn) + } + + // Fetch uptimes from all peers. This may fail to due to lack + // of read-quorum availability. + uptime, err := getPeerUptimes(globalAdminPeers) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + errorIf(err, "Unable to get uptime from majority of servers.") + return + } + + // Build server properties information + properties := ServerProperties{ + Version: Version, + CommitID: CommitID, + Region: serverConfig.GetRegion(), + SQSARN: arns, + Uptime: uptime, + } + + // Build network info + connStats := ServerConnStats{ + TotalInputBytes: globalConnStats.getTotalInputBytes(), + TotalOutputBytes: globalConnStats.getTotalOutputBytes(), + } + + // Build the whole returned information + info := ServerInfo{ + StorageInfo: storage, + ConnStats: connStats, + Properties: properties, + } + + // Marshal API response + jsonBytes, err := json.Marshal(info) + if err != nil { + writeErrorResponse(w, ErrInternalError, r.URL) + errorIf(err, "Failed to marshal storage info into json.") + return + } + // Reply with storage information (across nodes in a + // distributed setup) as json. + writeSuccessResponseJSON(w, jsonBytes) +} + // validateLockQueryParams - Validates query params for list/clear locks management APIs. func validateLockQueryParams(vars url.Values) (string, string, time.Duration, APIErrorCode) { bucket := vars.Get(string(mgmtBucket)) diff --git a/cmd/admin-router.go b/cmd/admin-router.go index 3136670f6..b22794c97 100644 --- a/cmd/admin-router.go +++ b/cmd/admin-router.go @@ -39,6 +39,9 @@ func registerAdminRouter(mux *router.Router) { // Service update credentials adminRouter.Methods("POST").Queries("service", "").Headers(minioAdminOpHeader, "set-credentials").HandlerFunc(adminAPI.ServiceCredentialsHandler) + // Info operations + adminRouter.Methods("GET").Queries("info", "").HandlerFunc(adminAPI.ServerInfoHandler) + /// Lock operations // List Locks diff --git a/cmd/event-notifier.go b/cmd/event-notifier.go index 8ebc5462d..9db12cccf 100644 --- a/cmd/event-notifier.go +++ b/cmd/event-notifier.go @@ -162,9 +162,22 @@ func newNotificationEvent(event eventData) NotificationEvent { return nEvent } -// Fetch the external target. No locking needed here since this map is -// never written after initial startup. +// Fetch all external targets. This returns a copy of the current map of +// external notification targets. +func (en eventNotifier) GetAllExternalTargets() map[string]*logrus.Logger { + en.external.rwMutex.RLock() + defer en.external.rwMutex.RUnlock() + targetsCopy := make(map[string]*logrus.Logger) + for k, v := range en.external.targets { + targetsCopy[k] = v + } + return targetsCopy +} + +// Fetch the external target. func (en eventNotifier) GetExternalTarget(queueARN string) *logrus.Logger { + en.external.rwMutex.RLock() + defer en.external.rwMutex.RUnlock() return en.external.targets[queueARN] } diff --git a/cmd/server-startup-msg.go b/cmd/server-startup-msg.go index 55012fc7c..53718aa74 100644 --- a/cmd/server-startup-msg.go +++ b/cmd/server-startup-msg.go @@ -101,10 +101,12 @@ func printEventNotifiers() { return } arnMsg := colorBlue("SQS ARNs: ") - if len(globalEventNotifier.external.targets) == 0 { + // Get all configured external notification targets + externalTargets := globalEventNotifier.GetAllExternalTargets() + if len(externalTargets) == 0 { arnMsg += colorBold(fmt.Sprintf(getFormatStr(len(""), 1), "")) } - for queueArn := range globalEventNotifier.external.targets { + for queueArn := range externalTargets { arnMsg += colorBold(fmt.Sprintf(getFormatStr(len(queueArn), 1), queueArn)) } console.Println(arnMsg) diff --git a/pkg/madmin/info-commands.go b/pkg/madmin/info-commands.go new file mode 100644 index 000000000..1c41fdf80 --- /dev/null +++ b/pkg/madmin/info-commands.go @@ -0,0 +1,119 @@ +/* + * Minio Cloud Storage, (C) 2017 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 madmin + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/url" + "time" +) + +// BackendType - represents different backend types. +type BackendType int + +// Enum for different backend types. +const ( + Unknown BackendType = iota + // Filesystem backend. + FS + // Multi disk Erasure (single, distributed) backend. + Erasure + + // Add your own backend. +) + +// StorageInfo - represents total capacity of underlying storage. +type StorageInfo struct { + // Total disk space. + Total int64 + // Free available disk space. + Free int64 + // Backend type. + Backend struct { + // Represents various backend types, currently on FS and Erasure. + Type BackendType + + // Following fields are only meaningful if BackendType is Erasure. + OnlineDisks int // Online disks during server startup. + OfflineDisks int // Offline disks during server startup. + ReadQuorum int // Minimum disks required for successful read operations. + WriteQuorum int // Minimum disks required for successful write operations. + } +} + +// ServerProperties holds some of the server's information such as uptime, +// version, region, .. +type ServerProperties struct { + Uptime time.Duration `json:"uptime"` + Version string `json:"version"` + CommitID string `json:"commitID"` + Region string `json:"region"` + SQSARN []string `json:"sqsARN"` +} + +// ServerConnStats holds network information +type ServerConnStats struct { + TotalInputBytes uint64 `json:"transferred"` + TotalOutputBytes uint64 `json:"received"` +} + +// ServerInfo holds the whole server information that will be +// returned by ServerInfo API. +type ServerInfo struct { + StorageInfo StorageInfo `json:"storage"` + ConnStats ServerConnStats `json:"network"` + Properties ServerProperties `json:"server"` +} + +// ServerInfo - Connect to a minio server and call Server Info Management API +// to fetch server's information represented by ServerInfo structure +func (adm *AdminClient) ServerInfo() (ServerInfo, error) { + // Prepare web service request + reqData := requestData{} + reqData.queryValues = make(url.Values) + reqData.queryValues.Set("info", "") + reqData.customHeaders = make(http.Header) + + resp, err := adm.executeMethod("GET", reqData) + defer closeResponse(resp) + if err != nil { + return ServerInfo{}, err + } + + // Check response http status code + if resp.StatusCode != http.StatusOK { + return ServerInfo{}, httpRespToErrorResponse(resp) + } + + // Unmarshal the server's json response + var info ServerInfo + + respBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return ServerInfo{}, err + } + + err = json.Unmarshal(respBytes, &info) + if err != nil { + return ServerInfo{}, err + } + + return info, nil +} diff --git a/pkg/madmin/service-commands.go b/pkg/madmin/service-commands.go index 292340ed7..ee22a3feb 100644 --- a/pkg/madmin/service-commands.go +++ b/pkg/madmin/service-commands.go @@ -1,5 +1,5 @@ /* - * Minio Cloud Storage, (C) 2016 Minio, Inc. + * Minio Cloud Storage, (C) 2016, 2017 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,50 +28,9 @@ import ( "time" ) -// BackendType - represents different backend types. -type BackendType int - -// Enum for different backend types. -const ( - Unknown BackendType = iota - // Filesystem backend. - FS - // Multi disk Erasure (single, distributed) backend. - Erasure - - // Add your own backend. -) - -// StorageInfo - represents total capacity of underlying storage. -type StorageInfo struct { - // Total disk space. - Total int64 - // Free available disk space. - Free int64 - // Backend type. - Backend struct { - // Represents various backend types, currently on FS and Erasure. - Type BackendType - - // Following fields are only meaningful if BackendType is Erasure. - OnlineDisks int // Online disks during server startup. - OfflineDisks int // Offline disks during server startup. - ReadQuorum int // Minimum disks required for successful read operations. - WriteQuorum int // Minimum disks required for successful write operations. - } -} - -// ServerVersion - server version -type ServerVersion struct { - Version string `json:"version"` - CommitID string `json:"commitID"` -} - // ServiceStatusMetadata - contains the response of service status API type ServiceStatusMetadata struct { - StorageInfo StorageInfo `json:"storageInfo"` - ServerVersion ServerVersion `json:"serverVersion"` - Uptime time.Duration `json:"uptime"` + Uptime time.Duration `json:"uptime"` } // ServiceStatus - Connect to a minio server and call Service Status Management API From f6a9e690bfa5911e980decb5a5164db19e031bd9 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 15 Feb 2017 11:29:23 -0800 Subject: [PATCH 73/75] browser: Update ui assets with new changes. --- browser/ui-assets.go | 82 ++++++++++++++++++++++---------------------- browser/yarn.lock | 68 +++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 45 deletions(-) diff --git a/browser/ui-assets.go b/browser/ui-assets.go index 2405f86b9..a8c48406d 100644 --- a/browser/ui-assets.go +++ b/browser/ui-assets.go @@ -4,7 +4,7 @@ // production/favicon.ico // production/firefox.png // production/index.html -// production/index_bundle-2017-02-02T11-00-00Z.js +// production/index_bundle-2017-02-15T19-26-44Z.js // production/loader.css // production/logo.svg // production/safari.png @@ -65,7 +65,7 @@ func productionChromePng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -82,7 +82,7 @@ func productionFaviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -99,7 +99,7 @@ func productionFirefoxPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -156,8 +156,8 @@ var _productionIndexHTML = []byte(` - - + + `) @@ -172,21 +172,21 @@ func productionIndexHTML() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _productionIndex_bundle20170202t110000zJs = []byte(`!function(A){function M(I){if(t[I])return t[I].exports;var g=t[I]={exports:{},id:I,loaded:!1};return A[I].call(g.exports,g,g.exports,M),g.loaded=!0,g.exports}var t={};return M.m=A,M.c=t,M.p="",M(0)}([function(A,M,t){A.exports=t(240)},function(A,M,t){"use strict";A.exports=t(439)},function(A,M,t){"use strict";function I(A,M,t,I,g,e,i,T){if(!A){var E;if(void 0===M)E=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var N=[t,I,g,e,i,T],o=0;E=new Error(M.replace(/%s/g,function(){return N[o++]})),E.name="Invariant Violation"}throw E.framesToPop=1,E}}A.exports=I},function(A,M,t){"use strict";var I=t(20),g=I;A.exports=g},function(A,M){"use strict";function t(A,M){if(null==A)throw new TypeError("Object.assign target cannot be null or undefined");for(var t=Object(A),I=Object.prototype.hasOwnProperty,g=1;g2?t-2:0),g=2;g1){for(var c=Array(C),D=0;D1){for(var a=Array(D),B=0;B3&&void 0!==arguments[3]?arguments[3]:{},N=Boolean(A),C=A||w,D=void 0;D="function"==typeof M?M:M?(0,Q.default)(M):L;var B=t||l,r=I.pure,s=void 0===r||r,x=I.withRef,y=void 0!==x&&x,h=s&&B!==l,S=d++;return function(A){function M(A,M,t){var I=B(A,M,t);return I}var t="Connect("+T(A)+")",I=function(I){function T(A,M){g(this,T);var i=e(this,I.call(this,A,M));i.version=S,i.store=A.store||M.store,(0,u.default)(i.store,'Could not find "store" in either the context or '+('props of "'+t+'". ')+"Either wrap the root component in a , "+('or explicitly pass "store" as a prop to "'+t+'".'));var E=i.store.getState();return i.state={storeState:E},i.clearCache(),i}return i(T,I),T.prototype.shouldComponentUpdate=function(){return!s||this.haveOwnPropsChanged||this.hasStoreStateChanged},T.prototype.computeStateProps=function(A,M){if(!this.finalMapStateToProps)return this.configureFinalMapState(A,M);var t=A.getState(),I=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(t,M):this.finalMapStateToProps(t);return I},T.prototype.configureFinalMapState=function(A,M){var t=C(A.getState(),M),I="function"==typeof t;return this.finalMapStateToProps=I?t:C,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,I?this.computeStateProps(A,M):t},T.prototype.computeDispatchProps=function(A,M){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(A,M);var t=A.dispatch,I=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(t,M):this.finalMapDispatchToProps(t);return I},T.prototype.configureFinalMapDispatch=function(A,M){var t=D(A.dispatch,M),I="function"==typeof t;return this.finalMapDispatchToProps=I?t:D,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,I?this.computeDispatchProps(A,M):t},T.prototype.updateStatePropsIfNeeded=function(){var A=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,a.default)(A,this.stateProps))&&(this.stateProps=A,!0)},T.prototype.updateDispatchPropsIfNeeded=function(){var A=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,a.default)(A,this.dispatchProps))&&(this.dispatchProps=A,!0)},T.prototype.updateMergedPropsIfNeeded=function(){var A=M(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&h&&(0,a.default)(A,this.mergedProps))&&(this.mergedProps=A,!0)},T.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},T.prototype.trySubscribe=function(){N&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},T.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},T.prototype.componentDidMount=function(){this.trySubscribe()},T.prototype.componentWillReceiveProps=function(A){s&&(0,a.default)(A,this.props)||(this.haveOwnPropsChanged=!0)},T.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},T.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},T.prototype.handleChange=function(){if(this.unsubscribe){var A=this.store.getState(),M=this.state.storeState;if(!s||M!==A){if(s&&!this.doStatePropsDependOnOwnProps){var t=E(this.updateStatePropsIfNeeded,this);if(!t)return;t===Y&&(this.statePropsPrecalculationError=Y.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:A})}}},T.prototype.getWrappedInstance=function(){return(0,u.default)(y,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},T.prototype.render=function(){var M=this.haveOwnPropsChanged,t=this.hasStoreStateChanged,I=this.haveStatePropsBeenPrecalculated,g=this.statePropsPrecalculationError,e=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,g)throw g;var i=!0,T=!0;s&&e&&(i=t||M&&this.doStatePropsDependOnOwnProps,T=M&&this.doDispatchPropsDependOnOwnProps);var E=!1,N=!1;I?E=!0:i&&(E=this.updateStatePropsIfNeeded()),T&&(N=this.updateDispatchPropsIfNeeded());var C=!0;return C=!!(E||N||M)&&this.updateMergedPropsIfNeeded(),!C&&e?e:(y?this.renderedElement=(0,n.createElement)(A,o({},this.mergedProps,{ref:"wrappedInstance"})):this.renderedElement=(0,n.createElement)(A,this.mergedProps),this.renderedElement)},T}(n.Component);return I.displayName=t,I.WrappedComponent=A,I.contextTypes={store:c.default},I.propTypes={store:c.default},(0,j.default)(I,A)}}M.__esModule=!0;var o=Object.assign||function(A){for(var M=1;M should not have a "'+M+'" prop')}M.__esModule=!0,M.routes=M.route=M.components=M.component=M.history=void 0,M.falsy=I;var g=t(1),e=g.PropTypes.func,i=g.PropTypes.object,T=g.PropTypes.arrayOf,E=g.PropTypes.oneOfType,N=g.PropTypes.element,o=g.PropTypes.shape,n=g.PropTypes.string,C=(M.history=o({listen:e.isRequired,push:e.isRequired,replace:e.isRequired,go:e.isRequired,goBack:e.isRequired,goForward:e.isRequired}),M.component=E([e,n])),c=(M.components=E([C,i]),M.route=E([i,N]));M.routes=E([c,T(c)])},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){var M=A.match(/^https?:\/\/[^\/]*/); -return null==M?A:A.substring(M[0].length)}function e(A){var M=g(A),t="",I="",e=M.indexOf("#");e!==-1&&(I=M.substring(e),M=M.substring(0,e));var i=M.indexOf("?");return i!==-1&&(t=M.substring(i),M=M.substring(0,i)),""===M&&(M="/"),{pathname:M,search:t,hash:I}}M.__esModule=!0,M.extractPath=g,M.parsePath=e;var i=t(23);I(i)},function(A,M,t){"use strict";function I(){g.attachRefs(this,this._currentElement)}var g=t(458),e={mountComponent:function(A,M,t,g){var e=A.mountComponent(M,t,g);return A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A),e},unmountComponent:function(A){g.detachRefs(A,A._currentElement),A.unmountComponent()},receiveComponent:function(A,M,t,e){var i=A._currentElement;if(M!==i||e!==A._context){var T=g.shouldUpdateRefs(i,M);T&&g.detachRefs(A,i),A.receiveComponent(M,t,e),T&&A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A)}},performUpdateIfNecessary:function(A,M){A.performUpdateIfNecessary(M)}};A.exports=e},function(A,M,t){"use strict";function I(A,M,t,I){this.dispatchConfig=A,this.dispatchMarker=M,this.nativeEvent=t;var g=this.constructor.Interface;for(var e in g)if(g.hasOwnProperty(e)){var T=g[e];T?this[e]=T(t):"target"===e?this.target=I:this[e]=t[e]}var E=null!=t.defaultPrevented?t.defaultPrevented:t.returnValue===!1;E?this.isDefaultPrevented=i.thatReturnsTrue:this.isDefaultPrevented=i.thatReturnsFalse,this.isPropagationStopped=i.thatReturnsFalse}var g=t(31),e=t(4),i=t(20),T=(t(3),{type:null,target:null,currentTarget:i.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(A){return A.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null});e(I.prototype,{preventDefault:function(){this.defaultPrevented=!0;var A=this.nativeEvent;A&&(A.preventDefault?A.preventDefault():A.returnValue=!1,this.isDefaultPrevented=i.thatReturnsTrue)},stopPropagation:function(){var A=this.nativeEvent;A&&(A.stopPropagation?A.stopPropagation():A.cancelBubble=!0,this.isPropagationStopped=i.thatReturnsTrue)},persist:function(){this.isPersistent=i.thatReturnsTrue},isPersistent:i.thatReturnsFalse,destructor:function(){var A=this.constructor.Interface;for(var M in A)this[M]=null;this.dispatchConfig=null,this.dispatchMarker=null,this.nativeEvent=null}}),I.Interface=T,I.augmentClass=function(A,M){var t=this,I=Object.create(t.prototype);e(I,A.prototype),A.prototype=I,A.prototype.constructor=A,A.Interface=e({},t.Interface,M),A.augmentClass=t.augmentClass,g.addPoolingTo(A,g.fourArgumentPooler)},g.addPoolingTo(I,g.fourArgumentPooler),A.exports=I},function(A,M){"use strict";M.default=function(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t},M.__esModule=!0},function(A,M){"use strict";function t(A){return A&&A.ownerDocument||document}M.__esModule=!0,M.default=t,A.exports=M.default},function(A,M,t){"use strict";var I=t(32),g=function(){var A=I&&document.documentElement;return A&&A.contains?function(A,M){return A.contains(M)}:A&&A.compareDocumentPosition?function(A,M){return A===M||!!(16&A.compareDocumentPosition(M))}:function(A,M){if(M)do if(M===A)return!0;while(M=M.parentNode);return!1}}();A.exports=g},function(A,M){function t(A){return"number"==typeof A&&A>-1&&A%1==0&&A<=I}var I=9007199254740991;A.exports=t},function(A,M,t){(function(A){!function(M,t){A.exports=t()}(this,function(){"use strict";function M(){return aI.apply(null,arguments)}function t(A){aI=A}function I(A){return A instanceof Array||"[object Array]"===Object.prototype.toString.call(A)}function g(A){return null!=A&&"[object Object]"===Object.prototype.toString.call(A)}function e(A){var M;for(M in A)return!1;return!0}function i(A){return"number"==typeof A||"[object Number]"===Object.prototype.toString.call(A)}function T(A){return A instanceof Date||"[object Date]"===Object.prototype.toString.call(A)}function E(A,M){var t,I=[];for(t=0;t0)for(t in rI)I=rI[t],g=M[I],B(g)||(A[I]=g);return A}function r(A){Q(this,A),this._d=new Date(null!=A._d?A._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),sI===!1&&(sI=!0,M.updateOffset(this),sI=!1)}function s(A){return A instanceof r||null!=A&&null!=A._isAMomentObject}function x(A){return A<0?Math.ceil(A)||0:Math.floor(A)}function j(A){var M=+A,t=0;return 0!==M&&isFinite(M)&&(t=x(M)),t}function y(A,M,t){var I,g=Math.min(A.length,M.length),e=Math.abs(A.length-M.length),i=0;for(I=0;I0?"future":"past"];return l(t)?t(M):t.replace(/%s/i,M)}function F(A,M){var t=A.toLowerCase();SI[t]=SI[t+"s"]=SI[M]=A}function f(A){return"string"==typeof A?SI[A]||SI[A.toLowerCase()]:void 0}function k(A){var M,t,I={};for(t in A)N(A,t)&&(M=f(t),M&&(I[M]=A[t]));return I}function R(A,M){zI[A]=M}function J(A){var M=[];for(var t in A)M.push({unit:t,priority:zI[t]});return M.sort(function(A,M){return A.priority-M.priority}),M}function G(A,t){return function(I){return null!=I?(b(this,A,I),M.updateOffset(this,t),this):H(this,A)}}function H(A,M){return A.isValid()?A._d["get"+(A._isUTC?"UTC":"")+M]():NaN}function b(A,M,t){A.isValid()&&A._d["set"+(A._isUTC?"UTC":"")+M](t)}function X(A){return A=f(A),l(this[A])?this[A]():this}function v(A,M){if("object"==typeof A){A=k(A);for(var t=J(A),I=0;I=0;return(e?t?"+":"":"-")+Math.pow(10,Math.max(0,g)).toString().substr(1)+I}function V(A,M,t,I){var g=I;"string"==typeof I&&(g=function(){return this[I]()}),A&&(mI[A]=g),M&&(mI[M[0]]=function(){return W(g.apply(this,arguments),M[1],M[2])}),t&&(mI[t]=function(){return this.localeData().ordinal(g.apply(this,arguments),A)})}function P(A){return A.match(/\[[\s\S]/)?A.replace(/^\[|\]$/g,""):A.replace(/\\/g,"")}function Z(A){var M,t,I=A.match(UI);for(M=0,t=I.length;M=0&&pI.test(A);)A=A.replace(pI,t),pI.lastIndex=0,I-=1;return A}function _(A,M,t){$I[A]=l(M)?M:function(A,I){return A&&t?t:M}}function $(A,M){return N($I,A)?$I[A](M._strict,M._locale):new RegExp(AA(A))}function AA(A){return MA(A.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(A,M,t,I,g){return M||t||I||g}))}function MA(A){return A.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function tA(A,M){var t,I=M;for("string"==typeof A&&(A=[A]),i(M)&&(I=function(A,t){t[M]=j(A)}),t=0;t=0&&isFinite(T.getFullYear())&&T.setFullYear(A),T}function xA(A){var M=new Date(Date.UTC.apply(null,arguments));return A<100&&A>=0&&isFinite(M.getUTCFullYear())&&M.setUTCFullYear(A),M}function jA(A,M,t){var I=7+M-t,g=(7+xA(A,0,I).getUTCDay()-M)%7;return-g+I-1}function yA(A,M,t,I,g){var e,i,T=(7+t-I)%7,E=jA(A,I,g),N=1+7*(M-1)+T+E;return N<=0?(e=A-1,i=BA(e)+N):N>BA(A)?(e=A+1,i=N-BA(A)):(e=A,i=N),{year:e,dayOfYear:i}}function uA(A,M,t){var I,g,e=jA(A.year(),M,t),i=Math.floor((A.dayOfYear()-e-1)/7)+1;return i<1?(g=A.year()-1,I=i+wA(g,M,t)):i>wA(A.year(),M,t)?(I=i-wA(A.year(),M,t),g=A.year()+1):(g=A.year(),I=i),{week:I,year:g}}function wA(A,M,t){var I=jA(A,M,t),g=jA(A+1,M,t);return(BA(A)-I+g)/7}function LA(A){return uA(A,this._week.dow,this._week.doy).week}function lA(){return this._week.dow}function YA(){return this._week.doy}function dA(A){var M=this.localeData().week(this);return null==A?M:this.add(7*(A-M),"d")}function hA(A){var M=uA(this,1,4).week;return null==A?M:this.add(7*(A-M),"d")}function SA(A,M){return"string"!=typeof A?A:isNaN(A)?(A=M.weekdaysParse(A),"number"==typeof A?A:null):parseInt(A,10)}function zA(A,M){return"string"==typeof A?M.weekdaysParse(A)%7||7:isNaN(A)?null:A}function UA(A,M){return A?I(this._weekdays)?this._weekdays[A.day()]:this._weekdays[this._weekdays.isFormat.test(M)?"format":"standalone"][A.day()]:this._weekdays}function pA(A){return A?this._weekdaysShort[A.day()]:this._weekdaysShort}function OA(A){return A?this._weekdaysMin[A.day()]:this._weekdaysMin}function mA(A,M,t){var I,g,e,i=A.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],I=0;I<7;++I)e=n([2e3,1]).day(I),this._minWeekdaysParse[I]=this.weekdaysMin(e,"").toLocaleLowerCase(),this._shortWeekdaysParse[I]=this.weekdaysShort(e,"").toLocaleLowerCase(),this._weekdaysParse[I]=this.weekdays(e,"").toLocaleLowerCase();return t?"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:null):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null):"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null)))}function FA(A,M,t){var I,g,e;if(this._weekdaysParseExact)return mA.call(this,A,M,t);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),I=0;I<7;I++){if(g=n([2e3,1]).day(I),t&&!this._fullWeekdaysParse[I]&&(this._fullWeekdaysParse[I]=new RegExp("^"+this.weekdays(g,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[I]=new RegExp("^"+this.weekdaysShort(g,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[I]=new RegExp("^"+this.weekdaysMin(g,"").replace(".",".?")+"$","i")),this._weekdaysParse[I]||(e="^"+this.weekdays(g,"")+"|^"+this.weekdaysShort(g,"")+"|^"+this.weekdaysMin(g,""),this._weekdaysParse[I]=new RegExp(e.replace(".",""),"i")),t&&"dddd"===M&&this._fullWeekdaysParse[I].test(A))return I;if(t&&"ddd"===M&&this._shortWeekdaysParse[I].test(A))return I;if(t&&"dd"===M&&this._minWeekdaysParse[I].test(A))return I;if(!t&&this._weekdaysParse[I].test(A))return I}}function fA(A){if(!this.isValid())return null!=A?this:NaN;var M=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=A?(A=SA(A,this.localeData()),this.add(A-M,"d")):M}function kA(A){if(!this.isValid())return null!=A?this:NaN;var M=(this.day()+7-this.localeData()._week.dow)%7;return null==A?M:this.add(A-M,"d")}function RA(A){if(!this.isValid())return null!=A?this:NaN;if(null!=A){var M=zA(A,this.localeData());return this.day(this.day()%7?M:M-7)}return this.day()||7}function JA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysStrictRegex:this._weekdaysRegex):(N(this,"_weekdaysRegex")||(this._weekdaysRegex=jg),this._weekdaysStrictRegex&&A?this._weekdaysStrictRegex:this._weekdaysRegex)}function GA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(N(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=yg),this._weekdaysShortStrictRegex&&A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function HA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(N(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=ug),this._weekdaysMinStrictRegex&&A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function bA(){function A(A,M){return M.length-A.length}var M,t,I,g,e,i=[],T=[],E=[],N=[];for(M=0;M<7;M++)t=n([2e3,1]).day(M),I=this.weekdaysMin(t,""),g=this.weekdaysShort(t,""),e=this.weekdays(t,""),i.push(I),T.push(g),E.push(e),N.push(I),N.push(g),N.push(e);for(i.sort(A),T.sort(A),E.sort(A),N.sort(A),M=0;M<7;M++)T[M]=MA(T[M]),E[M]=MA(E[M]),N[M]=MA(N[M]);this._weekdaysRegex=new RegExp("^("+N.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+E.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+T.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function XA(){return this.hours()%12||12}function vA(){return this.hours()||24}function WA(A,M){V(A,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),M)})}function VA(A,M){return M._meridiemParse}function PA(A){return"p"===(A+"").toLowerCase().charAt(0)}function ZA(A,M,t){return A>11?t?"pm":"PM":t?"am":"AM"}function KA(A){return A?A.toLowerCase().replace("_","-"):A}function qA(A){for(var M,t,I,g,e=0;e0;){if(I=_A(g.slice(0,M).join("-")))return I;if(t&&t.length>=M&&y(g,t,!0)>=M-1)break;M--}e++}return null}function _A(M){var t=null;if(!dg[M]&&"undefined"!=typeof A&&A&&A.exports)try{t=wg._abbr,!function(){var A=new Error('Cannot find module "./locale"');throw A.code="MODULE_NOT_FOUND",A}(),$A(t)}catch(A){}return dg[M]}function $A(A,M){var t;return A&&(t=B(M)?tM(A):AM(A,M),t&&(wg=t)),wg._abbr}function AM(A,M){if(null!==M){var t=Yg;if(M.abbr=A,null!=dg[A])L("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),t=dg[A]._config;else if(null!=M.parentLocale){if(null==dg[M.parentLocale])return hg[M.parentLocale]||(hg[M.parentLocale]=[]),hg[M.parentLocale].push({name:A,config:M}),null;t=dg[M.parentLocale]._config}return dg[A]=new h(d(t,M)),hg[A]&&hg[A].forEach(function(A){AM(A.name,A.config)}),$A(A),dg[A]}return delete dg[A],null}function MM(A,M){if(null!=M){var t,I=Yg;null!=dg[A]&&(I=dg[A]._config),M=d(I,M),t=new h(M),t.parentLocale=dg[A],dg[A]=t,$A(A)}else null!=dg[A]&&(null!=dg[A].parentLocale?dg[A]=dg[A].parentLocale:null!=dg[A]&&delete dg[A]);return dg[A]}function tM(A){var M;if(A&&A._locale&&A._locale._abbr&&(A=A._locale._abbr),!A)return wg;if(!I(A)){if(M=_A(A))return M;A=[A]}return qA(A)}function IM(){return uI(dg)}function gM(A){var M,t=A._a;return t&&c(A).overflow===-2&&(M=t[tg]<0||t[tg]>11?tg:t[Ig]<1||t[Ig]>eA(t[Mg],t[tg])?Ig:t[gg]<0||t[gg]>24||24===t[gg]&&(0!==t[eg]||0!==t[ig]||0!==t[Tg])?gg:t[eg]<0||t[eg]>59?eg:t[ig]<0||t[ig]>59?ig:t[Tg]<0||t[Tg]>999?Tg:-1,c(A)._overflowDayOfYear&&(MIg)&&(M=Ig),c(A)._overflowWeeks&&M===-1&&(M=Eg),c(A)._overflowWeekday&&M===-1&&(M=Ng),c(A).overflow=M),A}function eM(A){var M,t,I,g,e,i,T=A._i,E=Sg.exec(T)||zg.exec(T);if(E){for(c(A).iso=!0,M=0,t=pg.length;MBA(g)&&(c(A)._overflowDayOfYear=!0),t=xA(g,0,A._dayOfYear),A._a[tg]=t.getUTCMonth(),A._a[Ig]=t.getUTCDate()),M=0;M<3&&null==A._a[M];++M)A._a[M]=e[M]=I[M];for(;M<7;M++)A._a[M]=e[M]=null==A._a[M]?2===M?1:0:A._a[M];24===A._a[gg]&&0===A._a[eg]&&0===A._a[ig]&&0===A._a[Tg]&&(A._nextDay=!0,A._a[gg]=0),A._d=(A._useUTC?xA:sA).apply(null,e),null!=A._tzm&&A._d.setUTCMinutes(A._d.getUTCMinutes()-A._tzm),A._nextDay&&(A._a[gg]=24)}}function oM(A){var M,t,I,g,e,i,T,E;if(M=A._w,null!=M.GG||null!=M.W||null!=M.E)e=1,i=4,t=TM(M.GG,A._a[Mg],uA(sM(),1,4).year),I=TM(M.W,1),g=TM(M.E,1),(g<1||g>7)&&(E=!0);else{e=A._locale._week.dow,i=A._locale._week.doy;var N=uA(sM(),e,i);t=TM(M.gg,A._a[Mg],N.year),I=TM(M.w,N.week),null!=M.d?(g=M.d,(g<0||g>6)&&(E=!0)):null!=M.e?(g=M.e+e,(M.e<0||M.e>6)&&(E=!0)):g=e}I<1||I>wA(t,e,i)?c(A)._overflowWeeks=!0:null!=E?c(A)._overflowWeekday=!0:(T=yA(t,I,g,e,i),A._a[Mg]=T.year,A._dayOfYear=T.dayOfYear)}function nM(A){if(A._f===M.ISO_8601)return void eM(A);A._a=[],c(A).empty=!0;var t,I,g,e,i,T=""+A._i,E=T.length,N=0;for(g=q(A._f,A._locale).match(UI)||[],t=0;t0&&c(A).unusedInput.push(i),T=T.slice(T.indexOf(I)+I.length),N+=I.length),mI[e]?(I?c(A).empty=!1:c(A).unusedTokens.push(e),gA(e,I,A)):A._strict&&!I&&c(A).unusedTokens.push(e);c(A).charsLeftOver=E-N,T.length>0&&c(A).unusedInput.push(T),A._a[gg]<=12&&c(A).bigHour===!0&&A._a[gg]>0&&(c(A).bigHour=void 0),c(A).parsedDateParts=A._a.slice(0),c(A).meridiem=A._meridiem,A._a[gg]=CM(A._locale,A._a[gg],A._meridiem),NM(A),gM(A)}function CM(A,M,t){var I;return null==t?M:null!=A.meridiemHour?A.meridiemHour(M,t):null!=A.isPM?(I=A.isPM(t),I&&M<12&&(M+=12),I||12!==M||(M=0),M):M}function cM(A){var M,t,I,g,e;if(0===A._f.length)return c(A).invalidFormat=!0,void(A._d=new Date(NaN));for(g=0;gthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function fM(){if(!B(this._isDSTShifted))return this._isDSTShifted;var A={};if(Q(A,this),A=BM(A),A._a){var M=A._isUTC?n(A._a):sM(A._a);this._isDSTShifted=this.isValid()&&y(A._a,M.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function kM(){return!!this.isValid()&&!this._isUTC}function RM(){return!!this.isValid()&&this._isUTC}function JM(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function GM(A,M){var t,I,g,e=A,T=null;return wM(A)?e={ms:A._milliseconds,d:A._days,M:A._months}:i(A)?(e={},M?e[M]=A:e.milliseconds=A):(T=Jg.exec(A))?(t="-"===T[1]?-1:1,e={y:0,d:j(T[Ig])*t,h:j(T[gg])*t,m:j(T[eg])*t,s:j(T[ig])*t,ms:j(LM(1e3*T[Tg]))*t}):(T=Gg.exec(A))?(t="-"===T[1]?-1:1,e={y:HM(T[2],t),M:HM(T[3],t),w:HM(T[4],t),d:HM(T[5],t),h:HM(T[6],t),m:HM(T[7],t),s:HM(T[8],t)}):null==e?e={}:"object"==typeof e&&("from"in e||"to"in e)&&(g=XM(sM(e.from),sM(e.to)),e={},e.ms=g.milliseconds,e.M=g.months),I=new uM(e),wM(A)&&N(A,"_locale")&&(I._locale=A._locale),I}function HM(A,M){var t=A&&parseFloat(A.replace(",","."));return(isNaN(t)?0:t)*M}function bM(A,M){var t={milliseconds:0,months:0};return t.months=M.month()-A.month()+12*(M.year()-A.year()),A.clone().add(t.months,"M").isAfter(M)&&--t.months,t.milliseconds=+M-+A.clone().add(t.months,"M"),t}function XM(A,M){var t;return A.isValid()&&M.isValid()?(M=dM(M,A),A.isBefore(M)?t=bM(A,M):(t=bM(M,A),t.milliseconds=-t.milliseconds,t.months=-t.months),t):{milliseconds:0,months:0}}function vM(A,M){return function(t,I){var g,e;return null===I||isNaN(+I)||(L(M,"moment()."+M+"(period, number) is deprecated. Please use moment()."+M+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),e=t,t=I,I=e),t="string"==typeof t?+t:t,g=GM(t,I),WM(this,g,A),this}}function WM(A,t,I,g){var e=t._milliseconds,i=LM(t._days),T=LM(t._months);A.isValid()&&(g=null==g||g,e&&A._d.setTime(A._d.valueOf()+e*I),i&&b(A,"Date",H(A,"Date")+i*I),T&&oA(A,H(A,"Month")+T*I),g&&M.updateOffset(A,i||T))}function VM(A,M){var t=A.diff(M,"days",!0);return t<-6?"sameElse":t<-1?"lastWeek":t<0?"lastDay":t<1?"sameDay":t<2?"nextDay":t<7?"nextWeek":"sameElse"}function PM(A,t){var I=A||sM(),g=dM(I,this).startOf("day"),e=M.calendarFormat(this,g)||"sameElse",i=t&&(l(t[e])?t[e].call(this,I):t[e]);return this.format(i||this.localeData().calendar(e,this,sM(I)))}function ZM(){return new r(this)}function KM(A,M){var t=s(A)?A:sM(A);return!(!this.isValid()||!t.isValid())&&(M=f(B(M)?"millisecond":M),"millisecond"===M?this.valueOf()>t.valueOf():t.valueOf()e&&(M=e),Ut.call(this,A,M,t,I,g))}function Ut(A,M,t,I,g){var e=yA(A,M,t,I,g),i=xA(e.year,0,e.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}function pt(A){return null==A?Math.ceil((this.month()+1)/3):this.month(3*(A-1)+this.month()%3)}function Ot(A){var M=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==A?M:this.add(A-M,"d")}function mt(A,M){M[Tg]=j(1e3*("0."+A))}function Ft(){return this._isUTC?"UTC":""}function ft(){return this._isUTC?"Coordinated Universal Time":""}function kt(A){return sM(1e3*A)}function Rt(){return sM.apply(null,arguments).parseZone()}function Jt(A){return A}function Gt(A,M,t,I){var g=tM(),e=n().set(I,M);return g[t](e,A)}function Ht(A,M,t){if(i(A)&&(M=A,A=void 0),A=A||"",null!=M)return Gt(A,M,t,"month");var I,g=[];for(I=0;I<12;I++)g[I]=Gt(A,I,t,"month");return g}function bt(A,M,t,I){"boolean"==typeof A?(i(M)&&(t=M,M=void 0),M=M||""):(M=A,t=M,A=!1,i(M)&&(t=M,M=void 0),M=M||"");var g=tM(),e=A?g._week.dow:0;if(null!=t)return Gt(M,(t+e)%7,I,"day");var T,E=[];for(T=0;T<7;T++)E[T]=Gt(M,(T+e)%7,I,"day");return E}function Xt(A,M){return Ht(A,M,"months")}function vt(A,M){return Ht(A,M,"monthsShort")}function Wt(A,M,t){return bt(A,M,t,"weekdays")}function Vt(A,M,t){return bt(A,M,t,"weekdaysShort")}function Pt(A,M,t){return bt(A,M,t,"weekdaysMin")}function Zt(){var A=this._data;return this._milliseconds=_g(this._milliseconds),this._days=_g(this._days),this._months=_g(this._months),A.milliseconds=_g(A.milliseconds),A.seconds=_g(A.seconds),A.minutes=_g(A.minutes),A.hours=_g(A.hours),A.months=_g(A.months),A.years=_g(A.years),this}function Kt(A,M,t,I){var g=GM(M,t);return A._milliseconds+=I*g._milliseconds,A._days+=I*g._days,A._months+=I*g._months,A._bubble()}function qt(A,M){return Kt(this,A,M,1)}function _t(A,M){return Kt(this,A,M,-1)}function $t(A){return A<0?Math.floor(A):Math.ceil(A)}function AI(){var A,M,t,I,g,e=this._milliseconds,i=this._days,T=this._months,E=this._data;return e>=0&&i>=0&&T>=0||e<=0&&i<=0&&T<=0||(e+=864e5*$t(tI(T)+i),i=0,T=0),E.milliseconds=e%1e3,A=x(e/1e3),E.seconds=A%60,M=x(A/60),E.minutes=M%60,t=x(M/60),E.hours=t%24,i+=x(t/24),g=x(MI(i)),T+=g,i-=$t(tI(g)),I=x(T/12),T%=12,E.days=i,E.months=T,E.years=I,this}function MI(A){return 4800*A/146097}function tI(A){return 146097*A/4800}function II(A){var M,t,I=this._milliseconds;if(A=f(A),"month"===A||"year"===A)return M=this._days+I/864e5,t=this._months+MI(M),"month"===A?t:t/12;switch(M=this._days+Math.round(tI(this._months)),A){case"week":return M/7+I/6048e5;case"day":return M+I/864e5;case"hour":return 24*M+I/36e5;case"minute":return 1440*M+I/6e4;case"second":return 86400*M+I/1e3;case"millisecond":return Math.floor(864e5*M)+I;default:throw new Error("Unknown unit "+A)}}function gI(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*j(this._months/12)}function eI(A){return function(){return this.as(A)}}function iI(A){return A=f(A),this[A+"s"]()}function TI(A){return function(){return this._data[A]}}function EI(){return x(this.days()/7)}function NI(A,M,t,I,g){return g.relativeTime(M||1,!!t,A,I)}function oI(A,M,t){var I=GM(A).abs(),g=De(I.as("s")),e=De(I.as("m")),i=De(I.as("h")),T=De(I.as("d")),E=De(I.as("M")),N=De(I.as("y")),o=g0,o[4]=t,NI.apply(null,o)}function nI(A){return void 0===A?De:"function"==typeof A&&(De=A,!0)}function CI(A,M){return void 0!==ae[A]&&(void 0===M?ae[A]:(ae[A]=M,!0))}function cI(A){var M=this.localeData(),t=oI(this,!A,M);return A&&(t=M.pastFuture(+this,t)),M.postformat(t)}function DI(){var A,M,t,I=Be(this._milliseconds)/1e3,g=Be(this._days),e=Be(this._months);A=x(I/60),M=x(A/60),I%=60,A%=60,t=x(e/12),e%=12;var i=t,T=e,E=g,N=M,o=A,n=I,C=this.asSeconds();return C?(C<0?"-":"")+"P"+(i?i+"Y":"")+(T?T+"M":"")+(E?E+"D":"")+(N||o||n?"T":"")+(N?N+"H":"")+(o?o+"M":"")+(n?n+"S":""):"P0D"}var aI,BI;BI=Array.prototype.some?Array.prototype.some:function(A){for(var M=Object(this),t=M.length>>>0,I=0;I68?1900:2e3)};var Bg=G("FullYear",!0);V("w",["ww",2],"wo","week"),V("W",["WW",2],"Wo","isoWeek"),F("week","w"),F("isoWeek","W"),R("week",5),R("isoWeek",5),_("w",GI),_("ww",GI,fI),_("W",GI),_("WW",GI,fI),IA(["w","ww","W","WW"],function(A,M,t,I){M[I.substr(0,1)]=j(A)});var Qg={dow:0,doy:6};V("d",0,"do","day"),V("dd",0,0,function(A){return this.localeData().weekdaysMin(this,A)}),V("ddd",0,0,function(A){return this.localeData().weekdaysShort(this,A)}),V("dddd",0,0,function(A){return this.localeData().weekdays(this,A)}),V("e",0,0,"weekday"),V("E",0,0,"isoWeekday"),F("day","d"),F("weekday","e"),F("isoWeekday","E"),R("day",11),R("weekday",11),R("isoWeekday",11),_("d",GI),_("e",GI),_("E",GI),_("dd",function(A,M){return M.weekdaysMinRegex(A)}),_("ddd",function(A,M){return M.weekdaysShortRegex(A)}),_("dddd",function(A,M){return M.weekdaysRegex(A)}),IA(["dd","ddd","dddd"],function(A,M,t,I){var g=t._locale.weekdaysParse(A,I,t._strict);null!=g?M.d=g:c(t).invalidWeekday=A}),IA(["d","e","E"],function(A,M,t,I){M[I]=j(A)});var rg="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),sg="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),xg="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),jg=_I,yg=_I,ug=_I;V("H",["HH",2],0,"hour"),V("h",["hh",2],0,XA),V("k",["kk",2],0,vA),V("hmm",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)}),V("hmmss",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)+W(this.seconds(),2)}),V("Hmm",0,0,function(){return""+this.hours()+W(this.minutes(),2)}),V("Hmmss",0,0,function(){return""+this.hours()+W(this.minutes(),2)+W(this.seconds(),2)}),WA("a",!0),WA("A",!1),F("hour","h"),R("hour",13),_("a",VA),_("A",VA),_("H",GI),_("h",GI),_("HH",GI,fI),_("hh",GI,fI),_("hmm",HI),_("hmmss",bI),_("Hmm",HI),_("Hmmss",bI),tA(["H","HH"],gg),tA(["a","A"],function(A,M,t){t._isPm=t._locale.isPM(A),t._meridiem=A}),tA(["h","hh"],function(A,M,t){M[gg]=j(A),c(t).bigHour=!0}),tA("hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I)),c(t).bigHour=!0}),tA("hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g)),c(t).bigHour=!0}),tA("Hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I))}),tA("Hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g))});var wg,Lg=/[ap]\.?m?\.?/i,lg=G("Hours",!0),Yg={calendar:wI,longDateFormat:LI,invalidDate:lI,ordinal:YI,ordinalParse:dI,relativeTime:hI,months:Cg,monthsShort:cg,week:Qg,weekdays:rg,weekdaysMin:xg,weekdaysShort:sg,meridiemParse:Lg},dg={},hg={},Sg=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,zg=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ug=/Z|[+-]\d\d(?::?\d\d)?/,pg=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Og=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],mg=/^\/?Date\((\-?\d+)/i;M.createFromInputFallback=w("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(A){A._d=new Date(A._i+(A._useUTC?" UTC":""))}),M.ISO_8601=function(){};var Fg=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var A=sM.apply(null,arguments);return this.isValid()&&A.isValid()?Athis?this:A:a()}),kg=function(){return Date.now?Date.now():+new Date};lM("Z",":"),lM("ZZ",""),_("Z",KI),_("ZZ",KI),tA(["Z","ZZ"],function(A,M,t){t._useUTC=!0,t._tzm=YM(KI,A)});var Rg=/([\+\-]|\d\d)/gi;M.updateOffset=function(){};var Jg=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Gg=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;GM.fn=uM.prototype;var Hg=vM(1,"add"),bg=vM(-1,"subtract");M.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",M.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xg=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(A){return void 0===A?this.localeData():this.locale(A)});V(0,["gg",2],0,function(){return this.weekYear()%100}),V(0,["GG",2],0,function(){return this.isoWeekYear()%100}),lt("gggg","weekYear"),lt("ggggg","weekYear"),lt("GGGG","isoWeekYear"),lt("GGGGG","isoWeekYear"),F("weekYear","gg"),F("isoWeekYear","GG"),R("weekYear",1),R("isoWeekYear",1),_("G",PI),_("g",PI),_("GG",GI,fI),_("gg",GI,fI),_("GGGG",vI,RI),_("gggg",vI,RI),_("GGGGG",WI,JI),_("ggggg",WI,JI),IA(["gggg","ggggg","GGGG","GGGGG"],function(A,M,t,I){M[I.substr(0,2)]=j(A)}),IA(["gg","GG"],function(A,t,I,g){t[g]=M.parseTwoDigitYear(A)}),V("Q",0,"Qo","quarter"),F("quarter","Q"),R("quarter",7),_("Q",FI),tA("Q",function(A,M){M[tg]=3*(j(A)-1)}),V("D",["DD",2],"Do","date"),F("date","D"),R("date",9),_("D",GI),_("DD",GI,fI),_("Do",function(A,M){return A?M._ordinalParse:M._ordinalParseLenient}),tA(["D","DD"],Ig),tA("Do",function(A,M){M[Ig]=j(A.match(GI)[0],10)});var vg=G("Date",!0);V("DDD",["DDDD",3],"DDDo","dayOfYear"),F("dayOfYear","DDD"),R("dayOfYear",4),_("DDD",XI),_("DDDD",kI),tA(["DDD","DDDD"],function(A,M,t){t._dayOfYear=j(A)}),V("m",["mm",2],0,"minute"),F("minute","m"),R("minute",14),_("m",GI),_("mm",GI,fI),tA(["m","mm"],eg);var Wg=G("Minutes",!1);V("s",["ss",2],0,"second"),F("second","s"),R("second",15),_("s",GI),_("ss",GI,fI),tA(["s","ss"],ig);var Vg=G("Seconds",!1);V("S",0,0,function(){return~~(this.millisecond()/100)}),V(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),V(0,["SSS",3],0,"millisecond"),V(0,["SSSS",4],0,function(){return 10*this.millisecond()}),V(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),V(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),V(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),V(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),V(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),F("millisecond","ms"),R("millisecond",16),_("S",XI,FI),_("SS",XI,fI),_("SSS",XI,kI);var Pg;for(Pg="SSSS";Pg.length<=9;Pg+="S")_(Pg,VI);for(Pg="S";Pg.length<=9;Pg+="S")tA(Pg,mt);var Zg=G("Milliseconds",!1);V("z",0,0,"zoneAbbr"),V("zz",0,0,"zoneName");var Kg=r.prototype;Kg.add=Hg,Kg.calendar=PM,Kg.clone=ZM,Kg.diff=tt,Kg.endOf=at,Kg.format=Tt,Kg.from=Et,Kg.fromNow=Nt,Kg.to=ot,Kg.toNow=nt,Kg.get=X,Kg.invalidAt=wt,Kg.isAfter=KM,Kg.isBefore=qM,Kg.isBetween=_M,Kg.isSame=$M,Kg.isSameOrAfter=At,Kg.isSameOrBefore=Mt,Kg.isValid=yt,Kg.lang=Xg,Kg.locale=Ct,Kg.localeData=ct,Kg.max=fg,Kg.min=Fg,Kg.parsingFlags=ut,Kg.set=v,Kg.startOf=Dt,Kg.subtract=bg,Kg.toArray=st,Kg.toObject=xt,Kg.toDate=rt,Kg.toISOString=et,Kg.inspect=it,Kg.toJSON=jt,Kg.toString=gt,Kg.unix=Qt,Kg.valueOf=Bt,Kg.creationData=Lt,Kg.year=Bg,Kg.isLeapYear=rA,Kg.weekYear=Yt,Kg.isoWeekYear=dt,Kg.quarter=Kg.quarters=pt,Kg.month=nA,Kg.daysInMonth=CA,Kg.week=Kg.weeks=dA,Kg.isoWeek=Kg.isoWeeks=hA,Kg.weeksInYear=St,Kg.isoWeeksInYear=ht,Kg.date=vg,Kg.day=Kg.days=fA,Kg.weekday=kA,Kg.isoWeekday=RA,Kg.dayOfYear=Ot,Kg.hour=Kg.hours=lg,Kg.minute=Kg.minutes=Wg,Kg.second=Kg.seconds=Vg,Kg.millisecond=Kg.milliseconds=Zg,Kg.utcOffset=SM,Kg.utc=UM,Kg.local=pM,Kg.parseZone=OM,Kg.hasAlignedHourOffset=mM,Kg.isDST=FM,Kg.isLocal=kM,Kg.isUtcOffset=RM,Kg.isUtc=JM,Kg.isUTC=JM,Kg.zoneAbbr=Ft,Kg.zoneName=ft,Kg.dates=w("dates accessor is deprecated. Use date instead.",vg),Kg.months=w("months accessor is deprecated. Use month instead",nA),Kg.years=w("years accessor is deprecated. Use year instead",Bg),Kg.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",zM),Kg.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",fM);var qg=h.prototype;qg.calendar=S,qg.longDateFormat=z,qg.invalidDate=U,qg.ordinal=p,qg.preparse=Jt,qg.postformat=Jt,qg.relativeTime=O,qg.pastFuture=m,qg.set=Y,qg.months=iA,qg.monthsShort=TA,qg.monthsParse=NA,qg.monthsRegex=DA,qg.monthsShortRegex=cA,qg.week=LA,qg.firstDayOfYear=YA,qg.firstDayOfWeek=lA,qg.weekdays=UA,qg.weekdaysMin=OA,qg.weekdaysShort=pA,qg.weekdaysParse=FA,qg.weekdaysRegex=JA,qg.weekdaysShortRegex=GA,qg.weekdaysMinRegex=HA,qg.isPM=PA,qg.meridiem=ZA,$A("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(A){var M=A%10,t=1===j(A%100/10)?"th":1===M?"st":2===M?"nd":3===M?"rd":"th";return A+t}}),M.lang=w("moment.lang is deprecated. Use moment.locale instead.",$A),M.langData=w("moment.langData is deprecated. Use moment.localeData instead.",tM);var _g=Math.abs,$g=eI("ms"),Ae=eI("s"),Me=eI("m"),te=eI("h"),Ie=eI("d"),ge=eI("w"),ee=eI("M"),ie=eI("y"),Te=TI("milliseconds"),Ee=TI("seconds"),Ne=TI("minutes"),oe=TI("hours"),ne=TI("days"),Ce=TI("months"),ce=TI("years"),De=Math.round,ae={s:45,m:45,h:22,d:26,M:11},Be=Math.abs,Qe=uM.prototype;return Qe.abs=Zt,Qe.add=qt,Qe.subtract=_t,Qe.as=II,Qe.asMilliseconds=$g,Qe.asSeconds=Ae,Qe.asMinutes=Me,Qe.asHours=te,Qe.asDays=Ie,Qe.asWeeks=ge,Qe.asMonths=ee,Qe.asYears=ie,Qe.valueOf=gI,Qe._bubble=AI,Qe.get=iI,Qe.milliseconds=Te,Qe.seconds=Ee,Qe.minutes=Ne,Qe.hours=oe,Qe.days=ne,Qe.weeks=EI,Qe.months=Ce,Qe.years=ce,Qe.humanize=cI,Qe.toISOString=DI,Qe.toString=DI,Qe.toJSON=DI,Qe.locale=Ct,Qe.localeData=ct,Qe.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",DI),Qe.lang=Xg,V("X",0,0,"unix"),V("x",0,0,"valueOf"),_("x",PI),_("X",qI),tA("X",function(A,M,t){t._d=new Date(1e3*parseFloat(A,10))}),tA("x",function(A,M,t){t._d=new Date(j(A))}),M.version="2.17.1",t(sM),M.fn=Kg,M.min=jM,M.max=yM,M.now=kg,M.utc=n,M.unix=kt,M.months=Xt,M.isDate=T,M.locale=$A,M.invalid=a,M.duration=GM,M.isMoment=s,M.weekdays=Wt,M.parseZone=Rt,M.localeData=tM,M.isDuration=wM,M.monthsShort=vt,M.weekdaysMin=Pt,M.defineLocale=AM,M.updateLocale=MM,M.locales=IM,M.weekdaysShort=Vt,M.normalizeUnits=f,M.relativeTimeRounding=nI,M.relativeTimeThreshold=CI,M.calendarFormat=VM,M.prototype=Kg,M})}).call(M,t(128)(A))},function(A,M,t){"use strict";var I=t(132).default,g=t(133).default,e=t(78).default;M.__esModule=!0;var i=function(A){return I(g({values:function(){var A=this;return e(this).map(function(M){return A[M]})}}),A)},T={SIZES:{large:"lg",medium:"md",small:"sm",xsmall:"xs",lg:"lg",md:"md",sm:"sm",xs:"xs"},GRID_COLUMNS:12},E=i({LARGE:"large",MEDIUM:"medium",SMALL:"small",XSMALL:"xsmall"});M.Sizes=E;var N=i({SUCCESS:"success",WARNING:"warning",DANGER:"danger",INFO:"info"});M.State=N;var o="default";M.DEFAULT=o;var n="primary";M.PRIMARY=n;var C="link";M.LINK=C;var c="inverse";M.INVERSE=c,M.default=T},function(A,M){"use strict";function t(){for(var A=arguments.length,M=Array(A),t=0;t0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURI(o))):"("===E?g+=1:")"===E?g-=1:":"===E.charAt(0)?(N=E.substring(1),o=M[N],null!=o||g>0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURIComponent(o))):e+=E;return e.replace(/\/+/g,"/")}M.__esModule=!0,M.compilePattern=i,M.matchPattern=T,M.getParamNames=E,M.getParams=N,M.formatPattern=o;var n=t(8),C=I(n),c=Object.create(null)},function(A,M){"use strict";M.__esModule=!0;var t="PUSH";M.PUSH=t;var I="REPLACE";M.REPLACE=I;var g="POP";M.POP=g,M.default={PUSH:t,REPLACE:I,POP:g}},function(A,M,t){"use strict";function I(A,M){return(A&M)===M}var g=t(2),e={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(A){var M=e,t=A.Properties||{},i=A.DOMAttributeNamespaces||{},E=A.DOMAttributeNames||{},N=A.DOMPropertyNames||{},o=A.DOMMutationMethods||{};A.isCustomAttribute&&T._isCustomAttributeFunctions.push(A.isCustomAttribute);for(var n in t){T.properties.hasOwnProperty(n)?g(!1):void 0;var C=n.toLowerCase(),c=t[n],D={attributeName:C,attributeNamespace:null,propertyName:n,mutationMethod:null,mustUseAttribute:I(c,M.MUST_USE_ATTRIBUTE),mustUseProperty:I(c,M.MUST_USE_PROPERTY),hasSideEffects:I(c,M.HAS_SIDE_EFFECTS),hasBooleanValue:I(c,M.HAS_BOOLEAN_VALUE),hasNumericValue:I(c,M.HAS_NUMERIC_VALUE),hasPositiveNumericValue:I(c,M.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:I(c,M.HAS_OVERLOADED_BOOLEAN_VALUE)};if(D.mustUseAttribute&&D.mustUseProperty?g(!1):void 0,!D.mustUseProperty&&D.hasSideEffects?g(!1):void 0,D.hasBooleanValue+D.hasNumericValue+D.hasOverloadedBooleanValue<=1?void 0:g(!1),E.hasOwnProperty(n)){var a=E[n];D.attributeName=a}i.hasOwnProperty(n)&&(D.attributeNamespace=i[n]),N.hasOwnProperty(n)&&(D.propertyName=N[n]),o.hasOwnProperty(n)&&(D.mutationMethod=o[n]),T.properties[n]=D}}},i={},T={ID_ATTRIBUTE_NAME:"data-reactid",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(A){for(var M=0;M1){var M=A.indexOf(c,1);return M>-1?A.substr(0,M):A}return null},traverseEnterLeave:function(A,M,t,I,g){var e=N(A,M);e!==A&&o(A,e,t,I,!1,!0),e!==M&&o(e,M,t,g,!0,!1)},traverseTwoPhase:function(A,M,t){A&&(o("",A,M,t,!0,!1),o(A,"",M,t,!1,!0))},traverseTwoPhaseSkipTarget:function(A,M,t){A&&(o("",A,M,t,!0,!0),o(A,"",M,t,!0,!0))},traverseAncestors:function(A,M,t){o("",A,M,t,!0,!1)},getFirstCommonAncestorID:N,_getNextDescendantID:E,isAncestorIDOf:i,SEPARATOR:c};A.exports=B},function(A,M){var t=A.exports={version:"1.2.6"};"number"==typeof __e&&(__e=t)},function(A,M,t){"use strict";var I={};A.exports=I},function(A,M,t){"use strict";function I(A,M,t){var I=0;return n.default.Children.map(A,function(A){if(n.default.isValidElement(A)){var g=I;return I++,M.call(t,A,g)}return A})}function g(A,M,t){var I=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I),I++)})}function e(A){var M=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&M++}),M}function i(A){var M=!1;return n.default.Children.forEach(A,function(A){!M&&n.default.isValidElement(A)&&(M=!0)}),M}function T(A,M){var t=void 0;return g(A,function(I,g){!t&&M(I,g,A)&&(t=I)}),t}function E(A,M,t){var I=0,g=[];return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I)&&g.push(A),I++)}),g}var N=t(6).default;M.__esModule=!0;var o=t(1),n=N(o);M.default={map:I,forEach:g,numberOf:e,find:T,findValidComponents:E,hasValidComponent:i},A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0}),M.default=function(A){return(0,T.default)(e.default.findDOMNode(A))};var g=t(16),e=I(g),i=t(39),T=I(i);A.exports=M.default},function(A,M,t){"use strict";var I=t(204),g=t(436),e=t(217),i=t(226),T=t(227),E=t(2),N=(t(3),{}),o=null,n=function(A,M){A&&(g.executeDispatchesInOrder(A,M),A.isPersistent()||A.constructor.release(A))},C=function(A){return n(A,!0)},c=function(A){return n(A,!1)},D=null,a={injection:{injectMount:g.injection.injectMount,injectInstanceHandle:function(A){D=A},getInstanceHandle:function(){return D},injectEventPluginOrder:I.injectEventPluginOrder,injectEventPluginsByName:I.injectEventPluginsByName},eventNameDispatchConfigs:I.eventNameDispatchConfigs,registrationNameModules:I.registrationNameModules,putListener:function(A,M,t){"function"!=typeof t?E(!1):void 0;var g=N[M]||(N[M]={});g[A]=t;var e=I.registrationNameModules[M];e&&e.didPutListener&&e.didPutListener(A,M,t)},getListener:function(A,M){var t=N[M];return t&&t[A]},deleteListener:function(A,M){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M);var g=N[M];g&&delete g[A]},deleteAllListeners:function(A){for(var M in N)if(N[M][A]){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M),delete N[M][A]}},extractEvents:function(A,M,t,g,e){for(var T,E=I.plugins,N=0;N1?I-1:0),e=1;e":">","<":"<",'"':""","'":"'"},e=/[&><"']/g;A.exports=I},function(A,M,t){"use strict";var I=t(10),g=/^[ \r\n\t\f]/,e=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,i=function(A,M){A.innerHTML=M};if("undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction&&(i=function(A,M){MSApp.execUnsafeLocalFunction(function(){A.innerHTML=M})}),I.canUseDOM){var T=document.createElement("div");T.innerHTML=" ",""===T.innerHTML&&(i=function(A,M){if(A.parentNode&&A.parentNode.replaceChild(A,A),g.test(M)||"<"===M[0]&&e.test(M)){A.innerHTML=String.fromCharCode(65279)+M;var t=A.firstChild;1===t.data.length?A.removeChild(t):t.deleteData(0,1)}else A.innerHTML=M})}A.exports=i},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=function(A){var M=A.label,t=A.id,I=A.name,g=A.value,i=A.onChange,T=A.type,E=A.spellCheck,N=A.required,o=A.readonly,n=A.autoComplete,C=A.align,c=A.className,D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n});return o&&(D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n,disabled:!0})),e.default.createElement("div",{className:"input-group "+C+" "+c},D,e.default.createElement("i",{className:"ig-helpers"}),e.default.createElement("label",{className:"ig-label"},M))};M.default=i},function(A,M,t){A.exports={default:t(259),__esModule:!0}},function(A,M,t){var I=t(265),g=t(49),e=t(134),i="prototype",T=function(A,M,t){var E,N,o,n=A&T.F,C=A&T.G,c=A&T.S,D=A&T.P,a=A&T.B,B=A&T.W,Q=C?g:g[M]||(g[M]={}),r=C?I:c?I[M]:(I[M]||{})[i];C&&(t=M);for(E in t)N=!n&&r&&E in r,N&&E in Q||(o=N?r[E]:t[E],Q[E]=C&&"function"!=typeof r[E]?t[E]:a&&N?e(o,I):B&&r[E]==o?function(A){var M=function(M){return this instanceof A?new A(M):A(M)};return M[i]=A[i],M}(o):D&&"function"==typeof o?e(Function.call,o):o,D&&((Q[i]||(Q[i]={}))[E]=o))};T.F=1,T.G=2,T.S=4,T.P=8,T.B=16,T.W=32,A.exports=T},function(A,M){var t=Object;A.exports={create:t.create,getProto:t.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:t.getOwnPropertyDescriptor,setDesc:t.defineProperty,setDescs:t.defineProperties,getKeys:t.keys,getNames:t.getOwnPropertyNames,getSymbols:t.getOwnPropertySymbols,each:[].forEach}},function(A,M,t){"use strict";var I=t(32),g=function(){};I&&(g=function(){return document.addEventListener?function(A,M,t,I){return A.addEventListener(M,t,I||!1)}:document.attachEvent?function(A,M,t){return A.attachEvent("on"+M,t)}:void 0}()),A.exports=g},function(A,M,t){"use strict";var I=t(145),g=t(295),e=t(290),i=t(291),T=Object.prototype.hasOwnProperty;A.exports=function(A,M,t){var E="",N=M;if("string"==typeof M){if(void 0===t)return A.style[I(M)]||e(A).getPropertyValue(g(M));(N={})[M]=t}for(var o in N)T.call(N,o)&&(N[o]||0===N[o]?E+=g(o)+":"+N[o]+";":i(A,g(o)));A.style.cssText+=";"+E}},function(A,M,t){(function(){var t=this,I=t.humanize,g={};"undefined"!=typeof A&&A.exports&&(M=A.exports=g),M.humanize=g,g.noConflict=function(){return t.humanize=I,this},g.pad=function(A,M,t,I){if(A+="",t?t.length>1&&(t=t.charAt(0)):t=" ",I=void 0===I?"left":"right","right"===I)for(;A.length4&&A<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th"},w:function(){return t.getDay()},z:function(){return(o.L()?i[o.n()]:e[o.n()])+o.j()-1},W:function(){var A=o.z()-o.N()+1.5;return g.pad(1+Math.floor(Math.abs(A)/7)+(A%7>3.5?1:0),2,"0")},F:function(){return N[t.getMonth()]},m:function(){return g.pad(o.n(),2,"0")},M:function(){return o.F().slice(0,3)},n:function(){return t.getMonth()+1},t:function(){return new Date(o.Y(),o.n(),0).getDate()},L:function(){return 1===new Date(o.Y(),1,29).getMonth()?1:0},o:function(){var A=o.n(),M=o.W();return o.Y()+(12===A&&M<9?-1:1===A&&M>9)},Y:function(){return t.getFullYear()},y:function(){return String(o.Y()).slice(-2)},a:function(){return t.getHours()>11?"pm":"am"},A:function(){return o.a().toUpperCase()},B:function(){var A=t.getTime()/1e3,M=A%86400+3600;M<0&&(M+=86400);var I=M/86.4%1e3;return A<0?Math.ceil(I):Math.floor(I)},g:function(){return o.G()%12||12},G:function(){return t.getHours()},h:function(){return g.pad(o.g(),2,"0")},H:function(){return g.pad(o.G(),2,"0")},i:function(){return g.pad(t.getMinutes(),2,"0")},s:function(){return g.pad(t.getSeconds(),2,"0")},u:function(){return g.pad(1e3*t.getMilliseconds(),6,"0")},O:function(){var A=t.getTimezoneOffset(),M=Math.abs(A);return(A>0?"-":"+")+g.pad(100*Math.floor(M/60)+M%60,4,"0")},P:function(){var A=o.O();return A.substr(0,3)+":"+A.substr(3,2)},Z:function(){return 60*-t.getTimezoneOffset()},c:function(){return"Y-m-d\\TH:i:sP".replace(I,T)},r:function(){return"D, d M Y H:i:s O".replace(I,T)},U:function(){return t.getTime()/1e3||0}};return A.replace(I,T)},g.numberFormat=function(A,M,t,I){M=isNaN(M)?2:Math.abs(M),t=void 0===t?".":t,I=void 0===I?",":I;var g=A<0?"-":"";A=Math.abs(+A||0);var e=parseInt(A.toFixed(M),10)+"",i=e.length>3?e.length%3:0;return g+(i?e.substr(0,i)+I:"")+e.substr(i).replace(/(\d{3})(?=\d)/g,"$1"+I)+(M?t+Math.abs(A-e).toFixed(M).slice(2):"")},g.naturalDay=function(A,M){A=void 0===A?g.time():A,M=void 0===M?"Y-m-d":M;var t=86400,I=new Date,e=new Date(I.getFullYear(),I.getMonth(),I.getDate()).getTime()/1e3;return A=e-t?"yesterday":A>=e&&A=e+t&&A-2)return(t>=0?"just ":"")+"now";if(t<60&&t>-60)return t>=0?Math.floor(t)+" seconds ago":"in "+Math.floor(-t)+" seconds";if(t<120&&t>-120)return t>=0?"about a minute ago":"in about a minute";if(t<3600&&t>-3600)return t>=0?Math.floor(t/60)+" minutes ago":"in "+Math.floor(-t/60)+" minutes";if(t<7200&&t>-7200)return t>=0?"about an hour ago":"in about an hour";if(t<86400&&t>-86400)return t>=0?Math.floor(t/3600)+" hours ago":"in "+Math.floor(-t/3600)+" hours";var I=172800;if(t-I)return t>=0?"1 day ago":"in 1 day";var e=2505600;if(t-e)return t>=0?Math.floor(t/86400)+" days ago":"in "+Math.floor(-t/86400)+" days";var i=5184e3;if(t-i)return t>=0?"about a month ago":"in about a month";var T=parseInt(g.date("Y",M),10),E=parseInt(g.date("Y",A),10),N=12*T+parseInt(g.date("n",M),10),o=12*E+parseInt(g.date("n",A),10),n=N-o;if(n<12&&n>-12)return n>=0?n+" months ago":"in "+-n+" months";var C=T-E;return C<2&&C>-2?C>=0?"a year ago":"in a year":C>=0?C+" years ago":"in "+-C+" years"},g.ordinal=function(A){A=parseInt(A,10),A=isNaN(A)?0:A;var M=A<0?"-":"";A=Math.abs(A);var t=A%100;return M+A+(t>4&&t<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th")},g.filesize=function(A,M,t,I,e,i){return M=void 0===M?1024:M,A<=0?"0 bytes":(A

    "),A=A.replace(/\n/g,"
    "),"

    "+A+"

    "},g.nl2br=function(A){return A.replace(/(\r\n|\n|\r)/g,"
    ")},g.truncatechars=function(A,M){return A.length<=M?A:A.substr(0,M)+"…"},g.truncatewords=function(A,M){var t=A.split(" ");return t.length0,Q=C.enumErrorProps&&(A===u||A instanceof Error),r=C.enumPrototypes&&T(A);++IM.documentElement.clientHeight;return{modalStyles:{paddingRight:I&&!g?Q.default():void 0,paddingLeft:!I&&g?Q.default():void 0}}}});X.Body=z.default,X.Header=p.default,X.Title=m.default,X.Footer=f.default,X.Dialog=h.default,X.TRANSITION_DURATION=300,X.BACKDROP_TRANSITION_DURATION=150,M.default=c.bsSizes([a.Sizes.LARGE,a.Sizes.SMALL],c.bsClass("modal",X)),A.exports=M.default},function(A,M,t){"use strict";var I=t(15).default,g=t(14).default,e=t(38).default,i=t(7).default,T=t(6).default;M.__esModule=!0;var E=t(1),N=T(E),o=t(5),n=T(o),C=t(11),c=T(C),D=t(44),a=T(D),B=function(A){function M(){g(this,M),A.apply(this,arguments)}return I(M,A),M.prototype.render=function(){var A=this.props,M=A["aria-label"],t=e(A,["aria-label"]),I=a.default(this.context.$bs_onModalHide,this.props.onHide);return N.default.createElement("div",i({},t,{className:n.default(this.props.className,c.default.prefix(this.props,"header"))}),this.props.closeButton&&N.default.createElement("button",{type:"button",className:"close","aria-label":M,onClick:I},N.default.createElement("span",{"aria-hidden":"true"},"×")),this.props.children)},M}(N.default.Component);B.propTypes={"aria-label":N.default.PropTypes.string,bsClass:N.default.PropTypes.string,closeButton:N.default.PropTypes.bool,onHide:N.default.PropTypes.func},B.contextTypes={$bs_onModalHide:N.default.PropTypes.func},B.defaultProps={"aria-label":"Close",closeButton:!1},M.default=C.bsClass("modal",B),A.exports=M.default},function(A,M,t){"use strict";function I(A,M){return Array.isArray(M)?M.indexOf(A)>=0:A===M}var g=t(7).default,e=t(78).default,i=t(6).default;M.__esModule=!0;var T=t(40),E=i(T),N=t(170),o=i(N),n=t(1),C=i(n),c=t(16),D=i(c),a=t(127),B=(i(a),t(370)),Q=i(B),r=t(44),s=i(r),x=C.default.createClass({displayName:"OverlayTrigger", -propTypes:g({},Q.default.propTypes,{trigger:C.default.PropTypes.oneOfType([C.default.PropTypes.oneOf(["click","hover","focus"]),C.default.PropTypes.arrayOf(C.default.PropTypes.oneOf(["click","hover","focus"]))]),delay:C.default.PropTypes.number,delayShow:C.default.PropTypes.number,delayHide:C.default.PropTypes.number,defaultOverlayShown:C.default.PropTypes.bool,overlay:C.default.PropTypes.node.isRequired,onBlur:C.default.PropTypes.func,onClick:C.default.PropTypes.func,onFocus:C.default.PropTypes.func,onMouseEnter:C.default.PropTypes.func,onMouseLeave:C.default.PropTypes.func,target:function(){},onHide:function(){},show:function(){}}),getDefaultProps:function(){return{defaultOverlayShown:!1,trigger:["hover","focus"]}},getInitialState:function(){return{isOverlayShown:this.props.defaultOverlayShown}},show:function(){this.setState({isOverlayShown:!0})},hide:function(){this.setState({isOverlayShown:!1})},toggle:function(){this.state.isOverlayShown?this.hide():this.show()},componentWillMount:function(){this.handleMouseOver=this.handleMouseOverOut.bind(null,this.handleDelayedShow),this.handleMouseOut=this.handleMouseOverOut.bind(null,this.handleDelayedHide)},componentDidMount:function(){this._mountNode=document.createElement("div"),this.renderOverlay()},renderOverlay:function(){D.default.unstable_renderSubtreeIntoContainer(this,this._overlay,this._mountNode)},componentWillUnmount:function(){D.default.unmountComponentAtNode(this._mountNode),this._mountNode=null,clearTimeout(this._hoverShowDelay),clearTimeout(this._hoverHideDelay)},componentDidUpdate:function(){this._mountNode&&this.renderOverlay()},getOverlayTarget:function(){return D.default.findDOMNode(this)},getOverlay:function(){var A=g({},o.default(this.props,e(Q.default.propTypes)),{show:this.state.isOverlayShown,onHide:this.hide,target:this.getOverlayTarget,onExit:this.props.onExit,onExiting:this.props.onExiting,onExited:this.props.onExited,onEnter:this.props.onEnter,onEntering:this.props.onEntering,onEntered:this.props.onEntered}),M=n.cloneElement(this.props.overlay,{placement:A.placement,container:A.container});return C.default.createElement(Q.default,A,M)},render:function(){var A=C.default.Children.only(this.props.children),M=A.props,t={"aria-describedby":this.props.overlay.props.id};return this._overlay=this.getOverlay(),t.onClick=s.default(M.onClick,this.props.onClick),I("click",this.props.trigger)&&(t.onClick=s.default(this.toggle,t.onClick)),I("hover",this.props.trigger)&&(t.onMouseOver=s.default(this.handleMouseOver,this.props.onMouseOver,M.onMouseOver),t.onMouseOut=s.default(this.handleMouseOut,this.props.onMouseOut,M.onMouseOut)),I("focus",this.props.trigger)&&(t.onFocus=s.default(this.handleDelayedShow,this.props.onFocus,M.onFocus),t.onBlur=s.default(this.handleDelayedHide,this.props.onBlur,M.onBlur)),n.cloneElement(A,t)},handleDelayedShow:function(){var A=this;if(null!=this._hoverHideDelay)return clearTimeout(this._hoverHideDelay),void(this._hoverHideDelay=null);if(!this.state.isOverlayShown&&null==this._hoverShowDelay){var M=null!=this.props.delayShow?this.props.delayShow:this.props.delay;return M?void(this._hoverShowDelay=setTimeout(function(){A._hoverShowDelay=null,A.show()},M)):void this.show()}},handleDelayedHide:function(){var A=this;if(null!=this._hoverShowDelay)return clearTimeout(this._hoverShowDelay),void(this._hoverShowDelay=null);if(this.state.isOverlayShown&&null==this._hoverHideDelay){var M=null!=this.props.delayHide?this.props.delayHide:this.props.delay;return M?void(this._hoverHideDelay=setTimeout(function(){A._hoverHideDelay=null,A.hide()},M)):void this.hide()}},handleMouseOverOut:function(A,M){var t=M.currentTarget,I=M.relatedTarget||M.nativeEvent.toElement;I&&(I===t||E.default(t,I))||A(M)}});M.default=x,A.exports=M.default},function(A,M,t){"use strict";var I=t(7).default,g=t(6).default;M.__esModule=!0;var e=t(1),i=g(e),T=t(5),E=g(T),N=t(11),o=g(N),n=t(183),C=g(n),c=i.default.createClass({displayName:"Tooltip",propTypes:{id:C.default(i.default.PropTypes.oneOfType([i.default.PropTypes.string,i.default.PropTypes.number])),placement:i.default.PropTypes.oneOf(["top","right","bottom","left"]),positionLeft:i.default.PropTypes.number,positionTop:i.default.PropTypes.number,arrowOffsetLeft:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),arrowOffsetTop:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),title:i.default.PropTypes.node},getDefaultProps:function(){return{bsClass:"tooltip",placement:"right"}},render:function(){var A,M=(A={},A[o.default.prefix(this.props)]=!0,A[this.props.placement]=!0,A),t=I({left:this.props.positionLeft,top:this.props.positionTop},this.props.style),g={left:this.props.arrowOffsetLeft,top:this.props.arrowOffsetTop};return i.default.createElement("div",I({role:"tooltip"},this.props,{className:E.default(this.props.className,M),style:t}),i.default.createElement("div",{className:o.default.prefix(this.props,"arrow"),style:g}),i.default.createElement("div",{className:o.default.prefix(this.props,"inner")},this.props.children))}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){return A="function"==typeof A?A():A,i.default.findDOMNode(A)||M}Object.defineProperty(M,"__esModule",{value:!0}),M.default=g;var e=t(16),i=I(e);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement. You can usually obtain a ReactComponent or DOMElement from a ReactElement by attaching a ref to it."):"object"===E&&"function"==typeof i.render||1===i.nodeType?null:new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement.")}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M,t){"use strict";function I(){function A(A,M,I){for(var g=0;g>",null!=t[I]?A(t,I,g):M?new Error("Required prop '"+I+"' was not specified in '"+g+"'."):void 0}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}M.__esModule=!0,M.errMsg=t,M.createChainableTypeChecker=I},function(A,M){"use strict";function t(A,M,t){function I(){return i=!0,T?void(N=[].concat(Array.prototype.slice.call(arguments))):void t.apply(this,arguments)}function g(){if(!i&&(E=!0,!T)){for(T=!0;!i&&e=A&&E&&(i=!0,t()))}}var e=0,i=!1,T=!1,E=!1,N=void 0;g()}function I(A,M,t){function I(A,M,I){i||(M?(i=!0,t(M)):(e[A]=I,i=++T===g,i&&t(null,e)))}var g=A.length,e=[];if(0===g)return t(null,e);var i=!1,T=0;A.forEach(function(A,t){M(A,t,function(A,M){I(t,A,M)})})}M.__esModule=!0,M.loopAsync=t,M.mapAsync=I},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0,M.router=M.routes=M.route=M.components=M.component=M.location=M.history=M.falsy=M.locationShape=M.routerShape=void 0;var e=t(1),i=t(66),T=(g(i),t(34)),E=I(T),N=t(9),o=(g(N),e.PropTypes.func),n=e.PropTypes.object,C=e.PropTypes.shape,c=e.PropTypes.string,D=M.routerShape=C({push:o.isRequired,replace:o.isRequired,go:o.isRequired,goBack:o.isRequired,goForward:o.isRequired,setRouteLeaveHook:o.isRequired,isActive:o.isRequired}),a=M.locationShape=C({pathname:c.isRequired,search:c.isRequired,state:n,action:c.isRequired,key:c}),B=M.falsy=E.falsy,Q=M.history=E.history,r=M.location=a,s=M.component=E.component,x=M.components=E.components,j=M.route=E.route,y=(M.routes=E.routes,M.router=D),u={falsy:B,history:Q,location:r,component:s,components:x,route:j,router:y};M.default=u},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!0;return!1}function e(A,M){function t(M){var t=!(arguments.length<=1||void 0===arguments[1])&&arguments[1],I=arguments.length<=2||void 0===arguments[2]?null:arguments[2],g=void 0;return t&&t!==!0||null!==I?(M={pathname:M,query:t},g=I||!1):(M=A.createLocation(M),g=t),(0,C.default)(M,g,s.location,s.routes,s.params)}function I(A,t){x&&x.location===A?e(x,t):(0,B.default)(M,A,function(M,I){M?t(M):I?e(i({},I,{location:A}),t):t()})}function e(A,M){function t(t,g){return t||g?I(t,g):void(0,D.default)(A,function(t,I){t?M(t):M(null,null,s=i({},A,{components:I}))})}function I(A,t){A?M(A):M(null,t)}var g=(0,N.default)(s,A),e=g.leaveRoutes,T=g.changeRoutes,E=g.enterRoutes;(0,o.runLeaveHooks)(e,s),e.filter(function(A){return E.indexOf(A)===-1}).forEach(a),(0,o.runChangeHooks)(T,s,A,function(M,g){return M||g?I(M,g):void(0,o.runEnterHooks)(E,A,t)})}function T(A){var M=arguments.length<=1||void 0===arguments[1]||arguments[1];return A.__id__||M&&(A.__id__=j++)}function E(A){return A.reduce(function(A,M){return A.push.apply(A,y[T(M)]),A},[])}function n(A,t){(0,B.default)(M,A,function(M,I){if(null==I)return void t();x=i({},I,{location:A});for(var g=E((0,N.default)(s,x).leaveRoutes),e=void 0,T=0,o=g.length;null==e&&T=32||13===M?M:0}A.exports=t},function(A,M){"use strict";function t(A){var M=this,t=M.nativeEvent;if(t.getModifierState)return t.getModifierState(A);var I=g[A];return!!I&&!!t[I]}function I(A){return t}var g={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};A.exports=I},function(A,M){"use strict";function t(A){var M=A.target||A.srcElement||window;return 3===M.nodeType?M.parentNode:M}A.exports=t},function(A,M){"use strict";function t(A){var M=A&&(I&&A[I]||A[g]);if("function"==typeof M)return M}var I="function"==typeof Symbol&&Symbol.iterator,g="@@iterator";A.exports=t},function(A,M,t){"use strict";function I(A){return"function"==typeof A&&"undefined"!=typeof A.prototype&&"function"==typeof A.prototype.mountComponent&&"function"==typeof A.prototype.receiveComponent}function g(A){var M;if(null===A||A===!1)M=new i(g);else if("object"==typeof A){var t=A;!t||"function"!=typeof t.type&&"string"!=typeof t.type?N(!1):void 0,M="string"==typeof t.type?T.createInternalComponent(t):I(t.type)?new t.type(t):new o}else"string"==typeof A||"number"==typeof A?M=T.createInstanceForText(A):N(!1);return M.construct(A),M._mountIndex=0,M._mountImage=null,M}var e=t(442),i=t(215),T=t(221),E=t(4),N=t(2),o=(t(3),function(){});E(o.prototype,e.Mixin,{_instantiateReactComponent:g}),A.exports=g},function(A,M,t){"use strict";/** +!function(){"use strict";function t(){for(var A=[],M=0;M2?t-2:0),g=2;g1){for(var c=Array(C),D=0;D1){for(var a=Array(D),B=0;B3&&void 0!==arguments[3]?arguments[3]:{},N=Boolean(A),C=A||w,D=void 0;D="function"==typeof M?M:M?(0,Q.default)(M):L;var B=t||l,r=I.pure,s=void 0===r||r,x=I.withRef,y=void 0!==x&&x,h=s&&B!==l,S=d++;return function(A){function M(A,M,t){var I=B(A,M,t);return I}var t="Connect("+T(A)+")",I=function(I){function T(A,M){g(this,T);var i=e(this,I.call(this,A,M));i.version=S,i.store=A.store||M.store,(0,u.default)(i.store,'Could not find "store" in either the context or '+('props of "'+t+'". ')+"Either wrap the root component in a , "+('or explicitly pass "store" as a prop to "'+t+'".'));var E=i.store.getState();return i.state={storeState:E},i.clearCache(),i}return i(T,I),T.prototype.shouldComponentUpdate=function(){return!s||this.haveOwnPropsChanged||this.hasStoreStateChanged},T.prototype.computeStateProps=function(A,M){if(!this.finalMapStateToProps)return this.configureFinalMapState(A,M);var t=A.getState(),I=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(t,M):this.finalMapStateToProps(t);return I},T.prototype.configureFinalMapState=function(A,M){var t=C(A.getState(),M),I="function"==typeof t;return this.finalMapStateToProps=I?t:C,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,I?this.computeStateProps(A,M):t},T.prototype.computeDispatchProps=function(A,M){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(A,M);var t=A.dispatch,I=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(t,M):this.finalMapDispatchToProps(t);return I},T.prototype.configureFinalMapDispatch=function(A,M){var t=D(A.dispatch,M),I="function"==typeof t;return this.finalMapDispatchToProps=I?t:D,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,I?this.computeDispatchProps(A,M):t},T.prototype.updateStatePropsIfNeeded=function(){var A=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,a.default)(A,this.stateProps))&&(this.stateProps=A,!0)},T.prototype.updateDispatchPropsIfNeeded=function(){var A=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,a.default)(A,this.dispatchProps))&&(this.dispatchProps=A,!0)},T.prototype.updateMergedPropsIfNeeded=function(){var A=M(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&h&&(0,a.default)(A,this.mergedProps))&&(this.mergedProps=A,!0)},T.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},T.prototype.trySubscribe=function(){N&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},T.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},T.prototype.componentDidMount=function(){this.trySubscribe()},T.prototype.componentWillReceiveProps=function(A){s&&(0,a.default)(A,this.props)||(this.haveOwnPropsChanged=!0)},T.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},T.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},T.prototype.handleChange=function(){if(this.unsubscribe){var A=this.store.getState(),M=this.state.storeState;if(!s||M!==A){if(s&&!this.doStatePropsDependOnOwnProps){var t=E(this.updateStatePropsIfNeeded,this);if(!t)return;t===Y&&(this.statePropsPrecalculationError=Y.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:A})}}},T.prototype.getWrappedInstance=function(){return(0,u.default)(y,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},T.prototype.render=function(){var M=this.haveOwnPropsChanged,t=this.hasStoreStateChanged,I=this.haveStatePropsBeenPrecalculated,g=this.statePropsPrecalculationError,e=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,g)throw g;var i=!0,T=!0;s&&e&&(i=t||M&&this.doStatePropsDependOnOwnProps,T=M&&this.doDispatchPropsDependOnOwnProps);var E=!1,N=!1;I?E=!0:i&&(E=this.updateStatePropsIfNeeded()),T&&(N=this.updateDispatchPropsIfNeeded());var C=!0;return C=!!(E||N||M)&&this.updateMergedPropsIfNeeded(),!C&&e?e:(y?this.renderedElement=(0,n.createElement)(A,o({},this.mergedProps,{ref:"wrappedInstance"})):this.renderedElement=(0,n.createElement)(A,this.mergedProps),this.renderedElement)},T}(n.Component);return I.displayName=t,I.WrappedComponent=A,I.contextTypes={store:c.default},I.propTypes={store:c.default},(0,j.default)(I,A)}}M.__esModule=!0;var o=Object.assign||function(A){for(var M=1;M should not have a "'+M+'" prop')}M.__esModule=!0, +M.routes=M.route=M.components=M.component=M.history=void 0,M.falsy=I;var g=t(1),e=g.PropTypes.func,i=g.PropTypes.object,T=g.PropTypes.arrayOf,E=g.PropTypes.oneOfType,N=g.PropTypes.element,o=g.PropTypes.shape,n=g.PropTypes.string,C=(M.history=o({listen:e.isRequired,push:e.isRequired,replace:e.isRequired,go:e.isRequired,goBack:e.isRequired,goForward:e.isRequired}),M.component=E([e,n])),c=(M.components=E([C,i]),M.route=E([i,N]));M.routes=E([c,T(c)])},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){var M=A.match(/^https?:\/\/[^\/]*/);return null==M?A:A.substring(M[0].length)}function e(A){var M=g(A),t="",I="",e=M.indexOf("#");e!==-1&&(I=M.substring(e),M=M.substring(0,e));var i=M.indexOf("?");return i!==-1&&(t=M.substring(i),M=M.substring(0,i)),""===M&&(M="/"),{pathname:M,search:t,hash:I}}M.__esModule=!0,M.extractPath=g,M.parsePath=e;var i=t(23);I(i)},function(A,M,t){"use strict";function I(){g.attachRefs(this,this._currentElement)}var g=t(459),e={mountComponent:function(A,M,t,g){var e=A.mountComponent(M,t,g);return A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A),e},unmountComponent:function(A){g.detachRefs(A,A._currentElement),A.unmountComponent()},receiveComponent:function(A,M,t,e){var i=A._currentElement;if(M!==i||e!==A._context){var T=g.shouldUpdateRefs(i,M);T&&g.detachRefs(A,i),A.receiveComponent(M,t,e),T&&A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A)}},performUpdateIfNecessary:function(A,M){A.performUpdateIfNecessary(M)}};A.exports=e},function(A,M,t){"use strict";function I(A,M,t,I){this.dispatchConfig=A,this.dispatchMarker=M,this.nativeEvent=t;var g=this.constructor.Interface;for(var e in g)if(g.hasOwnProperty(e)){var T=g[e];T?this[e]=T(t):"target"===e?this.target=I:this[e]=t[e]}var E=null!=t.defaultPrevented?t.defaultPrevented:t.returnValue===!1;E?this.isDefaultPrevented=i.thatReturnsTrue:this.isDefaultPrevented=i.thatReturnsFalse,this.isPropagationStopped=i.thatReturnsFalse}var g=t(31),e=t(4),i=t(20),T=(t(3),{type:null,target:null,currentTarget:i.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(A){return A.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null});e(I.prototype,{preventDefault:function(){this.defaultPrevented=!0;var A=this.nativeEvent;A&&(A.preventDefault?A.preventDefault():A.returnValue=!1,this.isDefaultPrevented=i.thatReturnsTrue)},stopPropagation:function(){var A=this.nativeEvent;A&&(A.stopPropagation?A.stopPropagation():A.cancelBubble=!0,this.isPropagationStopped=i.thatReturnsTrue)},persist:function(){this.isPersistent=i.thatReturnsTrue},isPersistent:i.thatReturnsFalse,destructor:function(){var A=this.constructor.Interface;for(var M in A)this[M]=null;this.dispatchConfig=null,this.dispatchMarker=null,this.nativeEvent=null}}),I.Interface=T,I.augmentClass=function(A,M){var t=this,I=Object.create(t.prototype);e(I,A.prototype),A.prototype=I,A.prototype.constructor=A,A.Interface=e({},t.Interface,M),A.augmentClass=t.augmentClass,g.addPoolingTo(A,g.fourArgumentPooler)},g.addPoolingTo(I,g.fourArgumentPooler),A.exports=I},function(A,M){"use strict";M.default=function(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t},M.__esModule=!0},function(A,M){"use strict";function t(A){return A&&A.ownerDocument||document}M.__esModule=!0,M.default=t,A.exports=M.default},function(A,M,t){"use strict";var I=t(32),g=function(){var A=I&&document.documentElement;return A&&A.contains?function(A,M){return A.contains(M)}:A&&A.compareDocumentPosition?function(A,M){return A===M||!!(16&A.compareDocumentPosition(M))}:function(A,M){if(M)do if(M===A)return!0;while(M=M.parentNode);return!1}}();A.exports=g},function(A,M){function t(A){return"number"==typeof A&&A>-1&&A%1==0&&A<=I}var I=9007199254740991;A.exports=t},function(A,M,t){(function(A){!function(M,t){A.exports=t()}(this,function(){"use strict";function M(){return aI.apply(null,arguments)}function t(A){aI=A}function I(A){return A instanceof Array||"[object Array]"===Object.prototype.toString.call(A)}function g(A){return null!=A&&"[object Object]"===Object.prototype.toString.call(A)}function e(A){var M;for(M in A)return!1;return!0}function i(A){return"number"==typeof A||"[object Number]"===Object.prototype.toString.call(A)}function T(A){return A instanceof Date||"[object Date]"===Object.prototype.toString.call(A)}function E(A,M){var t,I=[];for(t=0;t0)for(t in rI)I=rI[t],g=M[I],B(g)||(A[I]=g);return A}function r(A){Q(this,A),this._d=new Date(null!=A._d?A._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),sI===!1&&(sI=!0,M.updateOffset(this),sI=!1)}function s(A){return A instanceof r||null!=A&&null!=A._isAMomentObject}function x(A){return A<0?Math.ceil(A)||0:Math.floor(A)}function j(A){var M=+A,t=0;return 0!==M&&isFinite(M)&&(t=x(M)),t}function y(A,M,t){var I,g=Math.min(A.length,M.length),e=Math.abs(A.length-M.length),i=0;for(I=0;I0?"future":"past"];return l(t)?t(M):t.replace(/%s/i,M)}function F(A,M){var t=A.toLowerCase();SI[t]=SI[t+"s"]=SI[M]=A}function f(A){return"string"==typeof A?SI[A]||SI[A.toLowerCase()]:void 0}function k(A){var M,t,I={};for(t in A)N(A,t)&&(M=f(t),M&&(I[M]=A[t]));return I}function R(A,M){zI[A]=M}function J(A){var M=[];for(var t in A)M.push({unit:t,priority:zI[t]});return M.sort(function(A,M){return A.priority-M.priority}),M}function G(A,t){return function(I){return null!=I?(b(this,A,I),M.updateOffset(this,t),this):H(this,A)}}function H(A,M){return A.isValid()?A._d["get"+(A._isUTC?"UTC":"")+M]():NaN}function b(A,M,t){A.isValid()&&A._d["set"+(A._isUTC?"UTC":"")+M](t)}function X(A){return A=f(A),l(this[A])?this[A]():this}function v(A,M){if("object"==typeof A){A=k(A);for(var t=J(A),I=0;I=0;return(e?t?"+":"":"-")+Math.pow(10,Math.max(0,g)).toString().substr(1)+I}function V(A,M,t,I){var g=I;"string"==typeof I&&(g=function(){return this[I]()}),A&&(mI[A]=g),M&&(mI[M[0]]=function(){return W(g.apply(this,arguments),M[1],M[2])}),t&&(mI[t]=function(){return this.localeData().ordinal(g.apply(this,arguments),A)})}function P(A){return A.match(/\[[\s\S]/)?A.replace(/^\[|\]$/g,""):A.replace(/\\/g,"")}function Z(A){var M,t,I=A.match(pI);for(M=0,t=I.length;M=0&&UI.test(A);)A=A.replace(UI,t),UI.lastIndex=0,I-=1;return A}function _(A,M,t){$I[A]=l(M)?M:function(A,I){return A&&t?t:M}}function $(A,M){return N($I,A)?$I[A](M._strict,M._locale):new RegExp(AA(A))}function AA(A){return MA(A.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(A,M,t,I,g){return M||t||I||g}))}function MA(A){return A.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function tA(A,M){var t,I=M;for("string"==typeof A&&(A=[A]),i(M)&&(I=function(A,t){t[M]=j(A)}),t=0;t=0&&isFinite(T.getFullYear())&&T.setFullYear(A),T}function xA(A){var M=new Date(Date.UTC.apply(null,arguments));return A<100&&A>=0&&isFinite(M.getUTCFullYear())&&M.setUTCFullYear(A),M}function jA(A,M,t){var I=7+M-t,g=(7+xA(A,0,I).getUTCDay()-M)%7;return-g+I-1}function yA(A,M,t,I,g){var e,i,T=(7+t-I)%7,E=jA(A,I,g),N=1+7*(M-1)+T+E;return N<=0?(e=A-1,i=BA(e)+N):N>BA(A)?(e=A+1,i=N-BA(A)):(e=A,i=N),{year:e,dayOfYear:i}}function uA(A,M,t){var I,g,e=jA(A.year(),M,t),i=Math.floor((A.dayOfYear()-e-1)/7)+1;return i<1?(g=A.year()-1,I=i+wA(g,M,t)):i>wA(A.year(),M,t)?(I=i-wA(A.year(),M,t),g=A.year()+1):(g=A.year(),I=i),{week:I,year:g}}function wA(A,M,t){var I=jA(A,M,t),g=jA(A+1,M,t);return(BA(A)-I+g)/7}function LA(A){return uA(A,this._week.dow,this._week.doy).week}function lA(){return this._week.dow}function YA(){return this._week.doy}function dA(A){var M=this.localeData().week(this);return null==A?M:this.add(7*(A-M),"d")}function hA(A){var M=uA(this,1,4).week;return null==A?M:this.add(7*(A-M),"d")}function SA(A,M){return"string"!=typeof A?A:isNaN(A)?(A=M.weekdaysParse(A),"number"==typeof A?A:null):parseInt(A,10)}function zA(A,M){return"string"==typeof A?M.weekdaysParse(A)%7||7:isNaN(A)?null:A}function pA(A,M){return A?I(this._weekdays)?this._weekdays[A.day()]:this._weekdays[this._weekdays.isFormat.test(M)?"format":"standalone"][A.day()]:this._weekdays}function UA(A){return A?this._weekdaysShort[A.day()]:this._weekdaysShort}function OA(A){return A?this._weekdaysMin[A.day()]:this._weekdaysMin}function mA(A,M,t){var I,g,e,i=A.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],I=0;I<7;++I)e=n([2e3,1]).day(I),this._minWeekdaysParse[I]=this.weekdaysMin(e,"").toLocaleLowerCase(),this._shortWeekdaysParse[I]=this.weekdaysShort(e,"").toLocaleLowerCase(),this._weekdaysParse[I]=this.weekdays(e,"").toLocaleLowerCase();return t?"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:null):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null):"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null)))}function FA(A,M,t){var I,g,e;if(this._weekdaysParseExact)return mA.call(this,A,M,t);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),I=0;I<7;I++){if(g=n([2e3,1]).day(I),t&&!this._fullWeekdaysParse[I]&&(this._fullWeekdaysParse[I]=new RegExp("^"+this.weekdays(g,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[I]=new RegExp("^"+this.weekdaysShort(g,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[I]=new RegExp("^"+this.weekdaysMin(g,"").replace(".",".?")+"$","i")),this._weekdaysParse[I]||(e="^"+this.weekdays(g,"")+"|^"+this.weekdaysShort(g,"")+"|^"+this.weekdaysMin(g,""),this._weekdaysParse[I]=new RegExp(e.replace(".",""),"i")),t&&"dddd"===M&&this._fullWeekdaysParse[I].test(A))return I;if(t&&"ddd"===M&&this._shortWeekdaysParse[I].test(A))return I;if(t&&"dd"===M&&this._minWeekdaysParse[I].test(A))return I;if(!t&&this._weekdaysParse[I].test(A))return I}}function fA(A){if(!this.isValid())return null!=A?this:NaN;var M=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=A?(A=SA(A,this.localeData()),this.add(A-M,"d")):M}function kA(A){if(!this.isValid())return null!=A?this:NaN;var M=(this.day()+7-this.localeData()._week.dow)%7;return null==A?M:this.add(A-M,"d")}function RA(A){if(!this.isValid())return null!=A?this:NaN;if(null!=A){var M=zA(A,this.localeData());return this.day(this.day()%7?M:M-7)}return this.day()||7}function JA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysStrictRegex:this._weekdaysRegex):(N(this,"_weekdaysRegex")||(this._weekdaysRegex=jg),this._weekdaysStrictRegex&&A?this._weekdaysStrictRegex:this._weekdaysRegex)}function GA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(N(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=yg),this._weekdaysShortStrictRegex&&A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function HA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(N(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=ug),this._weekdaysMinStrictRegex&&A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function bA(){function A(A,M){return M.length-A.length}var M,t,I,g,e,i=[],T=[],E=[],N=[];for(M=0;M<7;M++)t=n([2e3,1]).day(M),I=this.weekdaysMin(t,""),g=this.weekdaysShort(t,""),e=this.weekdays(t,""),i.push(I),T.push(g),E.push(e),N.push(I),N.push(g),N.push(e);for(i.sort(A),T.sort(A),E.sort(A),N.sort(A),M=0;M<7;M++)T[M]=MA(T[M]),E[M]=MA(E[M]),N[M]=MA(N[M]);this._weekdaysRegex=new RegExp("^("+N.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+E.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+T.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function XA(){return this.hours()%12||12}function vA(){return this.hours()||24}function WA(A,M){V(A,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),M)})}function VA(A,M){return M._meridiemParse}function PA(A){return"p"===(A+"").toLowerCase().charAt(0)}function ZA(A,M,t){return A>11?t?"pm":"PM":t?"am":"AM"}function KA(A){return A?A.toLowerCase().replace("_","-"):A}function qA(A){for(var M,t,I,g,e=0;e0;){if(I=_A(g.slice(0,M).join("-")))return I;if(t&&t.length>=M&&y(g,t,!0)>=M-1)break;M--}e++}return null}function _A(M){var t=null;if(!dg[M]&&"undefined"!=typeof A&&A&&A.exports)try{t=wg._abbr,!function(){var A=new Error('Cannot find module "./locale"');throw A.code="MODULE_NOT_FOUND",A}(),$A(t)}catch(A){}return dg[M]}function $A(A,M){var t;return A&&(t=B(M)?tM(A):AM(A,M),t&&(wg=t)),wg._abbr}function AM(A,M){if(null!==M){var t=Yg;if(M.abbr=A,null!=dg[A])L("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),t=dg[A]._config;else if(null!=M.parentLocale){if(null==dg[M.parentLocale])return hg[M.parentLocale]||(hg[M.parentLocale]=[]),hg[M.parentLocale].push({name:A,config:M}),null;t=dg[M.parentLocale]._config}return dg[A]=new h(d(t,M)),hg[A]&&hg[A].forEach(function(A){AM(A.name,A.config)}),$A(A),dg[A]}return delete dg[A],null}function MM(A,M){if(null!=M){var t,I=Yg;null!=dg[A]&&(I=dg[A]._config),M=d(I,M),t=new h(M),t.parentLocale=dg[A],dg[A]=t,$A(A)}else null!=dg[A]&&(null!=dg[A].parentLocale?dg[A]=dg[A].parentLocale:null!=dg[A]&&delete dg[A]);return dg[A]}function tM(A){var M;if(A&&A._locale&&A._locale._abbr&&(A=A._locale._abbr),!A)return wg;if(!I(A)){if(M=_A(A))return M;A=[A]}return qA(A)}function IM(){return uI(dg)}function gM(A){var M,t=A._a;return t&&c(A).overflow===-2&&(M=t[tg]<0||t[tg]>11?tg:t[Ig]<1||t[Ig]>eA(t[Mg],t[tg])?Ig:t[gg]<0||t[gg]>24||24===t[gg]&&(0!==t[eg]||0!==t[ig]||0!==t[Tg])?gg:t[eg]<0||t[eg]>59?eg:t[ig]<0||t[ig]>59?ig:t[Tg]<0||t[Tg]>999?Tg:-1,c(A)._overflowDayOfYear&&(MIg)&&(M=Ig),c(A)._overflowWeeks&&M===-1&&(M=Eg),c(A)._overflowWeekday&&M===-1&&(M=Ng),c(A).overflow=M),A}function eM(A){var M,t,I,g,e,i,T=A._i,E=Sg.exec(T)||zg.exec(T);if(E){for(c(A).iso=!0,M=0,t=Ug.length;MBA(g)&&(c(A)._overflowDayOfYear=!0),t=xA(g,0,A._dayOfYear),A._a[tg]=t.getUTCMonth(),A._a[Ig]=t.getUTCDate()),M=0;M<3&&null==A._a[M];++M)A._a[M]=e[M]=I[M];for(;M<7;M++)A._a[M]=e[M]=null==A._a[M]?2===M?1:0:A._a[M];24===A._a[gg]&&0===A._a[eg]&&0===A._a[ig]&&0===A._a[Tg]&&(A._nextDay=!0,A._a[gg]=0),A._d=(A._useUTC?xA:sA).apply(null,e),null!=A._tzm&&A._d.setUTCMinutes(A._d.getUTCMinutes()-A._tzm),A._nextDay&&(A._a[gg]=24)}}function oM(A){var M,t,I,g,e,i,T,E;if(M=A._w,null!=M.GG||null!=M.W||null!=M.E)e=1,i=4,t=TM(M.GG,A._a[Mg],uA(sM(),1,4).year),I=TM(M.W,1),g=TM(M.E,1),(g<1||g>7)&&(E=!0);else{e=A._locale._week.dow,i=A._locale._week.doy;var N=uA(sM(),e,i);t=TM(M.gg,A._a[Mg],N.year),I=TM(M.w,N.week),null!=M.d?(g=M.d,(g<0||g>6)&&(E=!0)):null!=M.e?(g=M.e+e,(M.e<0||M.e>6)&&(E=!0)):g=e}I<1||I>wA(t,e,i)?c(A)._overflowWeeks=!0:null!=E?c(A)._overflowWeekday=!0:(T=yA(t,I,g,e,i),A._a[Mg]=T.year,A._dayOfYear=T.dayOfYear)}function nM(A){if(A._f===M.ISO_8601)return void eM(A);A._a=[],c(A).empty=!0;var t,I,g,e,i,T=""+A._i,E=T.length,N=0;for(g=q(A._f,A._locale).match(pI)||[],t=0;t0&&c(A).unusedInput.push(i),T=T.slice(T.indexOf(I)+I.length),N+=I.length),mI[e]?(I?c(A).empty=!1:c(A).unusedTokens.push(e),gA(e,I,A)):A._strict&&!I&&c(A).unusedTokens.push(e);c(A).charsLeftOver=E-N,T.length>0&&c(A).unusedInput.push(T),A._a[gg]<=12&&c(A).bigHour===!0&&A._a[gg]>0&&(c(A).bigHour=void 0),c(A).parsedDateParts=A._a.slice(0),c(A).meridiem=A._meridiem,A._a[gg]=CM(A._locale,A._a[gg],A._meridiem),NM(A),gM(A)}function CM(A,M,t){var I;return null==t?M:null!=A.meridiemHour?A.meridiemHour(M,t):null!=A.isPM?(I=A.isPM(t),I&&M<12&&(M+=12),I||12!==M||(M=0),M):M}function cM(A){var M,t,I,g,e;if(0===A._f.length)return c(A).invalidFormat=!0,void(A._d=new Date(NaN));for(g=0;gthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function fM(){if(!B(this._isDSTShifted))return this._isDSTShifted;var A={};if(Q(A,this),A=BM(A),A._a){var M=A._isUTC?n(A._a):sM(A._a);this._isDSTShifted=this.isValid()&&y(A._a,M.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function kM(){return!!this.isValid()&&!this._isUTC}function RM(){return!!this.isValid()&&this._isUTC}function JM(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function GM(A,M){var t,I,g,e=A,T=null;return wM(A)?e={ms:A._milliseconds,d:A._days,M:A._months}:i(A)?(e={},M?e[M]=A:e.milliseconds=A):(T=Jg.exec(A))?(t="-"===T[1]?-1:1,e={y:0,d:j(T[Ig])*t,h:j(T[gg])*t,m:j(T[eg])*t,s:j(T[ig])*t,ms:j(LM(1e3*T[Tg]))*t}):(T=Gg.exec(A))?(t="-"===T[1]?-1:1,e={y:HM(T[2],t),M:HM(T[3],t),w:HM(T[4],t),d:HM(T[5],t),h:HM(T[6],t),m:HM(T[7],t),s:HM(T[8],t)}):null==e?e={}:"object"==typeof e&&("from"in e||"to"in e)&&(g=XM(sM(e.from),sM(e.to)),e={},e.ms=g.milliseconds,e.M=g.months),I=new uM(e),wM(A)&&N(A,"_locale")&&(I._locale=A._locale),I}function HM(A,M){var t=A&&parseFloat(A.replace(",","."));return(isNaN(t)?0:t)*M}function bM(A,M){var t={milliseconds:0,months:0};return t.months=M.month()-A.month()+12*(M.year()-A.year()),A.clone().add(t.months,"M").isAfter(M)&&--t.months,t.milliseconds=+M-+A.clone().add(t.months,"M"),t}function XM(A,M){var t;return A.isValid()&&M.isValid()?(M=dM(M,A),A.isBefore(M)?t=bM(A,M):(t=bM(M,A),t.milliseconds=-t.milliseconds,t.months=-t.months),t):{milliseconds:0,months:0}}function vM(A,M){return function(t,I){var g,e;return null===I||isNaN(+I)||(L(M,"moment()."+M+"(period, number) is deprecated. Please use moment()."+M+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),e=t,t=I,I=e),t="string"==typeof t?+t:t,g=GM(t,I),WM(this,g,A),this}}function WM(A,t,I,g){var e=t._milliseconds,i=LM(t._days),T=LM(t._months);A.isValid()&&(g=null==g||g,e&&A._d.setTime(A._d.valueOf()+e*I),i&&b(A,"Date",H(A,"Date")+i*I),T&&oA(A,H(A,"Month")+T*I),g&&M.updateOffset(A,i||T))}function VM(A,M){var t=A.diff(M,"days",!0);return t<-6?"sameElse":t<-1?"lastWeek":t<0?"lastDay":t<1?"sameDay":t<2?"nextDay":t<7?"nextWeek":"sameElse"}function PM(A,t){var I=A||sM(),g=dM(I,this).startOf("day"),e=M.calendarFormat(this,g)||"sameElse",i=t&&(l(t[e])?t[e].call(this,I):t[e]);return this.format(i||this.localeData().calendar(e,this,sM(I)))}function ZM(){return new r(this)}function KM(A,M){var t=s(A)?A:sM(A);return!(!this.isValid()||!t.isValid())&&(M=f(B(M)?"millisecond":M),"millisecond"===M?this.valueOf()>t.valueOf():t.valueOf()e&&(M=e),pt.call(this,A,M,t,I,g))}function pt(A,M,t,I,g){var e=yA(A,M,t,I,g),i=xA(e.year,0,e.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}function Ut(A){return null==A?Math.ceil((this.month()+1)/3):this.month(3*(A-1)+this.month()%3)}function Ot(A){var M=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==A?M:this.add(A-M,"d")}function mt(A,M){M[Tg]=j(1e3*("0."+A))}function Ft(){return this._isUTC?"UTC":""}function ft(){return this._isUTC?"Coordinated Universal Time":""}function kt(A){return sM(1e3*A)}function Rt(){return sM.apply(null,arguments).parseZone()}function Jt(A){return A}function Gt(A,M,t,I){var g=tM(),e=n().set(I,M);return g[t](e,A)}function Ht(A,M,t){if(i(A)&&(M=A,A=void 0),A=A||"",null!=M)return Gt(A,M,t,"month");var I,g=[];for(I=0;I<12;I++)g[I]=Gt(A,I,t,"month");return g}function bt(A,M,t,I){"boolean"==typeof A?(i(M)&&(t=M,M=void 0),M=M||""):(M=A,t=M,A=!1,i(M)&&(t=M,M=void 0),M=M||"");var g=tM(),e=A?g._week.dow:0;if(null!=t)return Gt(M,(t+e)%7,I,"day");var T,E=[];for(T=0;T<7;T++)E[T]=Gt(M,(T+e)%7,I,"day");return E}function Xt(A,M){return Ht(A,M,"months")}function vt(A,M){return Ht(A,M,"monthsShort")}function Wt(A,M,t){return bt(A,M,t,"weekdays")}function Vt(A,M,t){return bt(A,M,t,"weekdaysShort")}function Pt(A,M,t){return bt(A,M,t,"weekdaysMin")}function Zt(){var A=this._data;return this._milliseconds=_g(this._milliseconds),this._days=_g(this._days),this._months=_g(this._months),A.milliseconds=_g(A.milliseconds),A.seconds=_g(A.seconds),A.minutes=_g(A.minutes),A.hours=_g(A.hours),A.months=_g(A.months),A.years=_g(A.years),this}function Kt(A,M,t,I){var g=GM(M,t);return A._milliseconds+=I*g._milliseconds,A._days+=I*g._days,A._months+=I*g._months,A._bubble()}function qt(A,M){return Kt(this,A,M,1)}function _t(A,M){return Kt(this,A,M,-1)}function $t(A){return A<0?Math.floor(A):Math.ceil(A)}function AI(){var A,M,t,I,g,e=this._milliseconds,i=this._days,T=this._months,E=this._data;return e>=0&&i>=0&&T>=0||e<=0&&i<=0&&T<=0||(e+=864e5*$t(tI(T)+i),i=0,T=0),E.milliseconds=e%1e3,A=x(e/1e3),E.seconds=A%60,M=x(A/60),E.minutes=M%60,t=x(M/60),E.hours=t%24,i+=x(t/24),g=x(MI(i)),T+=g,i-=$t(tI(g)),I=x(T/12),T%=12,E.days=i,E.months=T,E.years=I,this}function MI(A){return 4800*A/146097}function tI(A){return 146097*A/4800}function II(A){var M,t,I=this._milliseconds;if(A=f(A),"month"===A||"year"===A)return M=this._days+I/864e5,t=this._months+MI(M),"month"===A?t:t/12;switch(M=this._days+Math.round(tI(this._months)),A){case"week":return M/7+I/6048e5;case"day":return M+I/864e5;case"hour":return 24*M+I/36e5;case"minute":return 1440*M+I/6e4;case"second":return 86400*M+I/1e3;case"millisecond":return Math.floor(864e5*M)+I;default:throw new Error("Unknown unit "+A)}}function gI(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*j(this._months/12)}function eI(A){return function(){return this.as(A)}}function iI(A){return A=f(A),this[A+"s"]()}function TI(A){return function(){return this._data[A]}}function EI(){return x(this.days()/7)}function NI(A,M,t,I,g){return g.relativeTime(M||1,!!t,A,I)}function oI(A,M,t){var I=GM(A).abs(),g=De(I.as("s")),e=De(I.as("m")),i=De(I.as("h")),T=De(I.as("d")),E=De(I.as("M")),N=De(I.as("y")),o=g0,o[4]=t,NI.apply(null,o)}function nI(A){return void 0===A?De:"function"==typeof A&&(De=A,!0)}function CI(A,M){return void 0!==ae[A]&&(void 0===M?ae[A]:(ae[A]=M,!0))}function cI(A){var M=this.localeData(),t=oI(this,!A,M);return A&&(t=M.pastFuture(+this,t)),M.postformat(t)}function DI(){var A,M,t,I=Be(this._milliseconds)/1e3,g=Be(this._days),e=Be(this._months);A=x(I/60),M=x(A/60),I%=60,A%=60,t=x(e/12),e%=12;var i=t,T=e,E=g,N=M,o=A,n=I,C=this.asSeconds();return C?(C<0?"-":"")+"P"+(i?i+"Y":"")+(T?T+"M":"")+(E?E+"D":"")+(N||o||n?"T":"")+(N?N+"H":"")+(o?o+"M":"")+(n?n+"S":""):"P0D"}var aI,BI;BI=Array.prototype.some?Array.prototype.some:function(A){for(var M=Object(this),t=M.length>>>0,I=0;I68?1900:2e3)};var Bg=G("FullYear",!0);V("w",["ww",2],"wo","week"),V("W",["WW",2],"Wo","isoWeek"),F("week","w"),F("isoWeek","W"),R("week",5),R("isoWeek",5),_("w",GI),_("ww",GI,fI),_("W",GI),_("WW",GI,fI),IA(["w","ww","W","WW"],function(A,M,t,I){M[I.substr(0,1)]=j(A)});var Qg={dow:0,doy:6};V("d",0,"do","day"),V("dd",0,0,function(A){return this.localeData().weekdaysMin(this,A)}),V("ddd",0,0,function(A){return this.localeData().weekdaysShort(this,A)}),V("dddd",0,0,function(A){return this.localeData().weekdays(this,A)}),V("e",0,0,"weekday"),V("E",0,0,"isoWeekday"),F("day","d"),F("weekday","e"),F("isoWeekday","E"),R("day",11),R("weekday",11),R("isoWeekday",11),_("d",GI),_("e",GI),_("E",GI),_("dd",function(A,M){return M.weekdaysMinRegex(A)}),_("ddd",function(A,M){return M.weekdaysShortRegex(A)}),_("dddd",function(A,M){return M.weekdaysRegex(A)}),IA(["dd","ddd","dddd"],function(A,M,t,I){var g=t._locale.weekdaysParse(A,I,t._strict);null!=g?M.d=g:c(t).invalidWeekday=A}),IA(["d","e","E"],function(A,M,t,I){M[I]=j(A)});var rg="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),sg="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),xg="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),jg=_I,yg=_I,ug=_I;V("H",["HH",2],0,"hour"),V("h",["hh",2],0,XA),V("k",["kk",2],0,vA),V("hmm",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)}),V("hmmss",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)+W(this.seconds(),2)}),V("Hmm",0,0,function(){return""+this.hours()+W(this.minutes(),2)}),V("Hmmss",0,0,function(){return""+this.hours()+W(this.minutes(),2)+W(this.seconds(),2)}),WA("a",!0),WA("A",!1),F("hour","h"),R("hour",13),_("a",VA),_("A",VA),_("H",GI),_("h",GI),_("HH",GI,fI),_("hh",GI,fI),_("hmm",HI),_("hmmss",bI),_("Hmm",HI),_("Hmmss",bI),tA(["H","HH"],gg),tA(["a","A"],function(A,M,t){t._isPm=t._locale.isPM(A),t._meridiem=A}),tA(["h","hh"],function(A,M,t){M[gg]=j(A),c(t).bigHour=!0}),tA("hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I)),c(t).bigHour=!0}),tA("hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g)),c(t).bigHour=!0}),tA("Hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I))}),tA("Hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g))});var wg,Lg=/[ap]\.?m?\.?/i,lg=G("Hours",!0),Yg={calendar:wI,longDateFormat:LI,invalidDate:lI,ordinal:YI,ordinalParse:dI,relativeTime:hI,months:Cg,monthsShort:cg,week:Qg,weekdays:rg,weekdaysMin:xg,weekdaysShort:sg,meridiemParse:Lg},dg={},hg={},Sg=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,zg=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,pg=/Z|[+-]\d\d(?::?\d\d)?/,Ug=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Og=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],mg=/^\/?Date\((\-?\d+)/i;M.createFromInputFallback=w("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(A){A._d=new Date(A._i+(A._useUTC?" UTC":""))}),M.ISO_8601=function(){};var Fg=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var A=sM.apply(null,arguments);return this.isValid()&&A.isValid()?Athis?this:A:a()}),kg=function(){return Date.now?Date.now():+new Date};lM("Z",":"),lM("ZZ",""),_("Z",KI),_("ZZ",KI),tA(["Z","ZZ"],function(A,M,t){t._useUTC=!0,t._tzm=YM(KI,A)});var Rg=/([\+\-]|\d\d)/gi;M.updateOffset=function(){};var Jg=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Gg=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;GM.fn=uM.prototype;var Hg=vM(1,"add"),bg=vM(-1,"subtract");M.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",M.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xg=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(A){return void 0===A?this.localeData():this.locale(A)});V(0,["gg",2],0,function(){return this.weekYear()%100}),V(0,["GG",2],0,function(){return this.isoWeekYear()%100}),lt("gggg","weekYear"),lt("ggggg","weekYear"),lt("GGGG","isoWeekYear"),lt("GGGGG","isoWeekYear"),F("weekYear","gg"),F("isoWeekYear","GG"),R("weekYear",1),R("isoWeekYear",1),_("G",PI),_("g",PI),_("GG",GI,fI),_("gg",GI,fI),_("GGGG",vI,RI),_("gggg",vI,RI),_("GGGGG",WI,JI),_("ggggg",WI,JI),IA(["gggg","ggggg","GGGG","GGGGG"],function(A,M,t,I){M[I.substr(0,2)]=j(A)}),IA(["gg","GG"],function(A,t,I,g){t[g]=M.parseTwoDigitYear(A)}),V("Q",0,"Qo","quarter"),F("quarter","Q"),R("quarter",7),_("Q",FI),tA("Q",function(A,M){M[tg]=3*(j(A)-1)}),V("D",["DD",2],"Do","date"),F("date","D"),R("date",9),_("D",GI),_("DD",GI,fI),_("Do",function(A,M){return A?M._ordinalParse:M._ordinalParseLenient}),tA(["D","DD"],Ig),tA("Do",function(A,M){M[Ig]=j(A.match(GI)[0],10)});var vg=G("Date",!0);V("DDD",["DDDD",3],"DDDo","dayOfYear"),F("dayOfYear","DDD"),R("dayOfYear",4),_("DDD",XI),_("DDDD",kI),tA(["DDD","DDDD"],function(A,M,t){t._dayOfYear=j(A)}),V("m",["mm",2],0,"minute"),F("minute","m"),R("minute",14),_("m",GI),_("mm",GI,fI),tA(["m","mm"],eg);var Wg=G("Minutes",!1);V("s",["ss",2],0,"second"),F("second","s"),R("second",15),_("s",GI),_("ss",GI,fI),tA(["s","ss"],ig);var Vg=G("Seconds",!1);V("S",0,0,function(){return~~(this.millisecond()/100)}),V(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),V(0,["SSS",3],0,"millisecond"),V(0,["SSSS",4],0,function(){return 10*this.millisecond()}),V(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),V(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),V(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),V(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),V(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),F("millisecond","ms"),R("millisecond",16),_("S",XI,FI),_("SS",XI,fI),_("SSS",XI,kI);var Pg;for(Pg="SSSS";Pg.length<=9;Pg+="S")_(Pg,VI);for(Pg="S";Pg.length<=9;Pg+="S")tA(Pg,mt);var Zg=G("Milliseconds",!1);V("z",0,0,"zoneAbbr"),V("zz",0,0,"zoneName");var Kg=r.prototype;Kg.add=Hg,Kg.calendar=PM,Kg.clone=ZM,Kg.diff=tt,Kg.endOf=at,Kg.format=Tt,Kg.from=Et,Kg.fromNow=Nt,Kg.to=ot,Kg.toNow=nt,Kg.get=X,Kg.invalidAt=wt,Kg.isAfter=KM,Kg.isBefore=qM,Kg.isBetween=_M,Kg.isSame=$M,Kg.isSameOrAfter=At,Kg.isSameOrBefore=Mt,Kg.isValid=yt,Kg.lang=Xg,Kg.locale=Ct,Kg.localeData=ct,Kg.max=fg,Kg.min=Fg,Kg.parsingFlags=ut,Kg.set=v,Kg.startOf=Dt,Kg.subtract=bg,Kg.toArray=st,Kg.toObject=xt,Kg.toDate=rt,Kg.toISOString=et,Kg.inspect=it,Kg.toJSON=jt,Kg.toString=gt,Kg.unix=Qt,Kg.valueOf=Bt,Kg.creationData=Lt,Kg.year=Bg,Kg.isLeapYear=rA,Kg.weekYear=Yt,Kg.isoWeekYear=dt,Kg.quarter=Kg.quarters=Ut,Kg.month=nA,Kg.daysInMonth=CA,Kg.week=Kg.weeks=dA,Kg.isoWeek=Kg.isoWeeks=hA,Kg.weeksInYear=St,Kg.isoWeeksInYear=ht,Kg.date=vg,Kg.day=Kg.days=fA,Kg.weekday=kA,Kg.isoWeekday=RA,Kg.dayOfYear=Ot,Kg.hour=Kg.hours=lg,Kg.minute=Kg.minutes=Wg,Kg.second=Kg.seconds=Vg,Kg.millisecond=Kg.milliseconds=Zg,Kg.utcOffset=SM,Kg.utc=pM,Kg.local=UM,Kg.parseZone=OM,Kg.hasAlignedHourOffset=mM,Kg.isDST=FM,Kg.isLocal=kM,Kg.isUtcOffset=RM,Kg.isUtc=JM,Kg.isUTC=JM,Kg.zoneAbbr=Ft,Kg.zoneName=ft,Kg.dates=w("dates accessor is deprecated. Use date instead.",vg),Kg.months=w("months accessor is deprecated. Use month instead",nA),Kg.years=w("years accessor is deprecated. Use year instead",Bg),Kg.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",zM),Kg.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",fM);var qg=h.prototype;qg.calendar=S,qg.longDateFormat=z,qg.invalidDate=p,qg.ordinal=U,qg.preparse=Jt,qg.postformat=Jt,qg.relativeTime=O,qg.pastFuture=m,qg.set=Y,qg.months=iA,qg.monthsShort=TA,qg.monthsParse=NA,qg.monthsRegex=DA,qg.monthsShortRegex=cA,qg.week=LA,qg.firstDayOfYear=YA,qg.firstDayOfWeek=lA,qg.weekdays=pA,qg.weekdaysMin=OA,qg.weekdaysShort=UA,qg.weekdaysParse=FA,qg.weekdaysRegex=JA,qg.weekdaysShortRegex=GA,qg.weekdaysMinRegex=HA,qg.isPM=PA,qg.meridiem=ZA,$A("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(A){var M=A%10,t=1===j(A%100/10)?"th":1===M?"st":2===M?"nd":3===M?"rd":"th";return A+t}}),M.lang=w("moment.lang is deprecated. Use moment.locale instead.",$A),M.langData=w("moment.langData is deprecated. Use moment.localeData instead.",tM);var _g=Math.abs,$g=eI("ms"),Ae=eI("s"),Me=eI("m"),te=eI("h"),Ie=eI("d"),ge=eI("w"),ee=eI("M"),ie=eI("y"),Te=TI("milliseconds"),Ee=TI("seconds"),Ne=TI("minutes"),oe=TI("hours"),ne=TI("days"),Ce=TI("months"),ce=TI("years"),De=Math.round,ae={s:45,m:45,h:22,d:26,M:11},Be=Math.abs,Qe=uM.prototype;return Qe.abs=Zt,Qe.add=qt,Qe.subtract=_t,Qe.as=II,Qe.asMilliseconds=$g,Qe.asSeconds=Ae,Qe.asMinutes=Me,Qe.asHours=te,Qe.asDays=Ie,Qe.asWeeks=ge,Qe.asMonths=ee,Qe.asYears=ie,Qe.valueOf=gI,Qe._bubble=AI,Qe.get=iI,Qe.milliseconds=Te,Qe.seconds=Ee,Qe.minutes=Ne,Qe.hours=oe,Qe.days=ne,Qe.weeks=EI,Qe.months=Ce,Qe.years=ce,Qe.humanize=cI,Qe.toISOString=DI,Qe.toString=DI,Qe.toJSON=DI,Qe.locale=Ct,Qe.localeData=ct,Qe.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",DI),Qe.lang=Xg,V("X",0,0,"unix"),V("x",0,0,"valueOf"),_("x",PI),_("X",qI),tA("X",function(A,M,t){t._d=new Date(1e3*parseFloat(A,10))}),tA("x",function(A,M,t){t._d=new Date(j(A))}),M.version="2.17.1",t(sM),M.fn=Kg,M.min=jM,M.max=yM,M.now=kg,M.utc=n,M.unix=kt,M.months=Xt,M.isDate=T,M.locale=$A,M.invalid=a,M.duration=GM,M.isMoment=s,M.weekdays=Wt,M.parseZone=Rt,M.localeData=tM,M.isDuration=wM,M.monthsShort=vt,M.weekdaysMin=Pt,M.defineLocale=AM,M.updateLocale=MM,M.locales=IM,M.weekdaysShort=Vt,M.normalizeUnits=f,M.relativeTimeRounding=nI,M.relativeTimeThreshold=CI,M.calendarFormat=VM,M.prototype=Kg,M})}).call(M,t(128)(A))},function(A,M,t){"use strict";var I=t(132).default,g=t(133).default,e=t(78).default;M.__esModule=!0;var i=function(A){return I(g({values:function(){var A=this;return e(this).map(function(M){return A[M]})}}),A)},T={SIZES:{large:"lg",medium:"md",small:"sm",xsmall:"xs",lg:"lg",md:"md",sm:"sm",xs:"xs"},GRID_COLUMNS:12},E=i({LARGE:"large",MEDIUM:"medium",SMALL:"small",XSMALL:"xsmall"});M.Sizes=E;var N=i({SUCCESS:"success",WARNING:"warning",DANGER:"danger",INFO:"info"});M.State=N;var o="default";M.DEFAULT=o;var n="primary";M.PRIMARY=n;var C="link";M.LINK=C;var c="inverse";M.INVERSE=c,M.default=T},function(A,M){"use strict";function t(){for(var A=arguments.length,M=Array(A),t=0;t0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURI(o))):"("===E?g+=1:")"===E?g-=1:":"===E.charAt(0)?(N=E.substring(1),o=M[N],null!=o||g>0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURIComponent(o))):e+=E;return e.replace(/\/+/g,"/")}M.__esModule=!0,M.compilePattern=i,M.matchPattern=T,M.getParamNames=E,M.getParams=N,M.formatPattern=o;var n=t(8),C=I(n),c=Object.create(null)},function(A,M){"use strict";M.__esModule=!0;var t="PUSH";M.PUSH=t;var I="REPLACE";M.REPLACE=I;var g="POP";M.POP=g,M.default={PUSH:t,REPLACE:I,POP:g}},function(A,M,t){"use strict";function I(A,M){return(A&M)===M}var g=t(2),e={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(A){var M=e,t=A.Properties||{},i=A.DOMAttributeNamespaces||{},E=A.DOMAttributeNames||{},N=A.DOMPropertyNames||{},o=A.DOMMutationMethods||{};A.isCustomAttribute&&T._isCustomAttributeFunctions.push(A.isCustomAttribute);for(var n in t){T.properties.hasOwnProperty(n)?g(!1):void 0;var C=n.toLowerCase(),c=t[n],D={attributeName:C,attributeNamespace:null,propertyName:n,mutationMethod:null,mustUseAttribute:I(c,M.MUST_USE_ATTRIBUTE),mustUseProperty:I(c,M.MUST_USE_PROPERTY),hasSideEffects:I(c,M.HAS_SIDE_EFFECTS),hasBooleanValue:I(c,M.HAS_BOOLEAN_VALUE),hasNumericValue:I(c,M.HAS_NUMERIC_VALUE),hasPositiveNumericValue:I(c,M.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:I(c,M.HAS_OVERLOADED_BOOLEAN_VALUE)};if(D.mustUseAttribute&&D.mustUseProperty?g(!1):void 0,!D.mustUseProperty&&D.hasSideEffects?g(!1):void 0,D.hasBooleanValue+D.hasNumericValue+D.hasOverloadedBooleanValue<=1?void 0:g(!1),E.hasOwnProperty(n)){var a=E[n];D.attributeName=a}i.hasOwnProperty(n)&&(D.attributeNamespace=i[n]),N.hasOwnProperty(n)&&(D.propertyName=N[n]),o.hasOwnProperty(n)&&(D.mutationMethod=o[n]),T.properties[n]=D}}},i={},T={ID_ATTRIBUTE_NAME:"data-reactid",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(A){for(var M=0;M1){var M=A.indexOf(c,1);return M>-1?A.substr(0,M):A}return null},traverseEnterLeave:function(A,M,t,I,g){var e=N(A,M);e!==A&&o(A,e,t,I,!1,!0),e!==M&&o(e,M,t,g,!0,!1)},traverseTwoPhase:function(A,M,t){A&&(o("",A,M,t,!0,!1),o(A,"",M,t,!1,!0))},traverseTwoPhaseSkipTarget:function(A,M,t){A&&(o("",A,M,t,!0,!0),o(A,"",M,t,!0,!0))},traverseAncestors:function(A,M,t){o("",A,M,t,!0,!1)},getFirstCommonAncestorID:N,_getNextDescendantID:E,isAncestorIDOf:i,SEPARATOR:c};A.exports=B},function(A,M){var t=A.exports={version:"1.2.6"};"number"==typeof __e&&(__e=t)},function(A,M,t){"use strict";var I={};A.exports=I},function(A,M,t){"use strict";function I(A,M,t){var I=0;return n.default.Children.map(A,function(A){if(n.default.isValidElement(A)){var g=I;return I++,M.call(t,A,g)}return A})}function g(A,M,t){var I=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I),I++)})}function e(A){var M=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&M++}),M}function i(A){var M=!1;return n.default.Children.forEach(A,function(A){!M&&n.default.isValidElement(A)&&(M=!0)}),M}function T(A,M){var t=void 0;return g(A,function(I,g){!t&&M(I,g,A)&&(t=I)}),t}function E(A,M,t){var I=0,g=[];return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I)&&g.push(A),I++)}),g}var N=t(6).default;M.__esModule=!0;var o=t(1),n=N(o);M.default={map:I,forEach:g,numberOf:e,find:T,findValidComponents:E,hasValidComponent:i},A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0}),M.default=function(A){return(0,T.default)(e.default.findDOMNode(A))};var g=t(16),e=I(g),i=t(39),T=I(i);A.exports=M.default},function(A,M,t){"use strict";var I=t(204),g=t(437),e=t(217),i=t(226),T=t(227),E=t(2),N=(t(3),{}),o=null,n=function(A,M){A&&(g.executeDispatchesInOrder(A,M),A.isPersistent()||A.constructor.release(A))},C=function(A){return n(A,!0)},c=function(A){return n(A,!1)},D=null,a={injection:{injectMount:g.injection.injectMount,injectInstanceHandle:function(A){D=A},getInstanceHandle:function(){return D},injectEventPluginOrder:I.injectEventPluginOrder,injectEventPluginsByName:I.injectEventPluginsByName},eventNameDispatchConfigs:I.eventNameDispatchConfigs,registrationNameModules:I.registrationNameModules,putListener:function(A,M,t){"function"!=typeof t?E(!1):void 0;var g=N[M]||(N[M]={});g[A]=t;var e=I.registrationNameModules[M];e&&e.didPutListener&&e.didPutListener(A,M,t)},getListener:function(A,M){var t=N[M];return t&&t[A]},deleteListener:function(A,M){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M);var g=N[M];g&&delete g[A]},deleteAllListeners:function(A){for(var M in N)if(N[M][A]){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M),delete N[M][A]}},extractEvents:function(A,M,t,g,e){for(var T,E=I.plugins,N=0;N1?I-1:0),e=1;e":">","<":"<",'"':""","'":"'"},e=/[&><"']/g;A.exports=I},function(A,M,t){"use strict";var I=t(10),g=/^[ \r\n\t\f]/,e=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,i=function(A,M){A.innerHTML=M};if("undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction&&(i=function(A,M){MSApp.execUnsafeLocalFunction(function(){A.innerHTML=M})}),I.canUseDOM){var T=document.createElement("div");T.innerHTML=" ",""===T.innerHTML&&(i=function(A,M){if(A.parentNode&&A.parentNode.replaceChild(A,A),g.test(M)||"<"===M[0]&&e.test(M)){A.innerHTML=String.fromCharCode(65279)+M;var t=A.firstChild;1===t.data.length?A.removeChild(t):t.deleteData(0,1)}else A.innerHTML=M})}A.exports=i},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=function(A){var M=A.label,t=A.id,I=A.name,g=A.value,i=A.onChange,T=A.type,E=A.spellCheck,N=A.required,o=A.readonly,n=A.autoComplete,C=A.align,c=A.className,D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n});return o&&(D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n,disabled:!0})),e.default.createElement("div",{className:"input-group "+C+" "+c},D,e.default.createElement("i",{className:"ig-helpers"}),e.default.createElement("label",{className:"ig-label"},M))};M.default=i},function(A,M,t){A.exports={default:t(259),__esModule:!0}},function(A,M,t){var I=t(265),g=t(49),e=t(134),i="prototype",T=function(A,M,t){var E,N,o,n=A&T.F,C=A&T.G,c=A&T.S,D=A&T.P,a=A&T.B,B=A&T.W,Q=C?g:g[M]||(g[M]={}),r=C?I:c?I[M]:(I[M]||{})[i];C&&(t=M);for(E in t)N=!n&&r&&E in r,N&&E in Q||(o=N?r[E]:t[E],Q[E]=C&&"function"!=typeof r[E]?t[E]:a&&N?e(o,I):B&&r[E]==o?function(A){var M=function(M){return this instanceof A?new A(M):A(M)};return M[i]=A[i],M}(o):D&&"function"==typeof o?e(Function.call,o):o,D&&((Q[i]||(Q[i]={}))[E]=o))};T.F=1,T.G=2,T.S=4,T.P=8,T.B=16,T.W=32,A.exports=T},function(A,M){var t=Object;A.exports={create:t.create,getProto:t.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:t.getOwnPropertyDescriptor,setDesc:t.defineProperty,setDescs:t.defineProperties,getKeys:t.keys,getNames:t.getOwnPropertyNames,getSymbols:t.getOwnPropertySymbols,each:[].forEach}},function(A,M,t){"use strict";var I=t(32),g=function(){};I&&(g=function(){return document.addEventListener?function(A,M,t,I){return A.addEventListener(M,t,I||!1)}:document.attachEvent?function(A,M,t){return A.attachEvent("on"+M,t)}:void 0}()),A.exports=g},function(A,M,t){"use strict";var I=t(145),g=t(295),e=t(290),i=t(291),T=Object.prototype.hasOwnProperty;A.exports=function(A,M,t){var E="",N=M;if("string"==typeof M){if(void 0===t)return A.style[I(M)]||e(A).getPropertyValue(g(M));(N={})[M]=t}for(var o in N)T.call(N,o)&&(N[o]||0===N[o]?E+=g(o)+":"+N[o]+";":i(A,g(o)));A.style.cssText+=";"+E}},function(A,M,t){(function(){var t=this,I=t.humanize,g={};"undefined"!=typeof A&&A.exports&&(M=A.exports=g),M.humanize=g,g.noConflict=function(){return t.humanize=I,this},g.pad=function(A,M,t,I){if(A+="",t?t.length>1&&(t=t.charAt(0)):t=" ",I=void 0===I?"left":"right","right"===I)for(;A.length4&&A<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th"},w:function(){return t.getDay()},z:function(){return(o.L()?i[o.n()]:e[o.n()])+o.j()-1},W:function(){var A=o.z()-o.N()+1.5;return g.pad(1+Math.floor(Math.abs(A)/7)+(A%7>3.5?1:0),2,"0")},F:function(){return N[t.getMonth()]},m:function(){return g.pad(o.n(),2,"0")},M:function(){return o.F().slice(0,3)},n:function(){return t.getMonth()+1},t:function(){return new Date(o.Y(),o.n(),0).getDate()},L:function(){return 1===new Date(o.Y(),1,29).getMonth()?1:0},o:function(){var A=o.n(),M=o.W();return o.Y()+(12===A&&M<9?-1:1===A&&M>9)},Y:function(){return t.getFullYear()},y:function(){return String(o.Y()).slice(-2)},a:function(){return t.getHours()>11?"pm":"am"},A:function(){return o.a().toUpperCase()},B:function(){var A=t.getTime()/1e3,M=A%86400+3600;M<0&&(M+=86400);var I=M/86.4%1e3;return A<0?Math.ceil(I):Math.floor(I)},g:function(){return o.G()%12||12},G:function(){return t.getHours()},h:function(){return g.pad(o.g(),2,"0")},H:function(){return g.pad(o.G(),2,"0")},i:function(){return g.pad(t.getMinutes(),2,"0")},s:function(){return g.pad(t.getSeconds(),2,"0")},u:function(){return g.pad(1e3*t.getMilliseconds(),6,"0")},O:function(){var A=t.getTimezoneOffset(),M=Math.abs(A);return(A>0?"-":"+")+g.pad(100*Math.floor(M/60)+M%60,4,"0")},P:function(){var A=o.O();return A.substr(0,3)+":"+A.substr(3,2)},Z:function(){return 60*-t.getTimezoneOffset()},c:function(){return"Y-m-d\\TH:i:sP".replace(I,T)},r:function(){return"D, d M Y H:i:s O".replace(I,T)},U:function(){return t.getTime()/1e3||0}};return A.replace(I,T)},g.numberFormat=function(A,M,t,I){M=isNaN(M)?2:Math.abs(M),t=void 0===t?".":t,I=void 0===I?",":I;var g=A<0?"-":"";A=Math.abs(+A||0);var e=parseInt(A.toFixed(M),10)+"",i=e.length>3?e.length%3:0;return g+(i?e.substr(0,i)+I:"")+e.substr(i).replace(/(\d{3})(?=\d)/g,"$1"+I)+(M?t+Math.abs(A-e).toFixed(M).slice(2):"")},g.naturalDay=function(A,M){A=void 0===A?g.time():A,M=void 0===M?"Y-m-d":M;var t=86400,I=new Date,e=new Date(I.getFullYear(),I.getMonth(),I.getDate()).getTime()/1e3;return A=e-t?"yesterday":A>=e&&A=e+t&&A-2)return(t>=0?"just ":"")+"now";if(t<60&&t>-60)return t>=0?Math.floor(t)+" seconds ago":"in "+Math.floor(-t)+" seconds";if(t<120&&t>-120)return t>=0?"about a minute ago":"in about a minute";if(t<3600&&t>-3600)return t>=0?Math.floor(t/60)+" minutes ago":"in "+Math.floor(-t/60)+" minutes";if(t<7200&&t>-7200)return t>=0?"about an hour ago":"in about an hour";if(t<86400&&t>-86400)return t>=0?Math.floor(t/3600)+" hours ago":"in "+Math.floor(-t/3600)+" hours";var I=172800;if(t-I)return t>=0?"1 day ago":"in 1 day";var e=2505600;if(t-e)return t>=0?Math.floor(t/86400)+" days ago":"in "+Math.floor(-t/86400)+" days";var i=5184e3;if(t-i)return t>=0?"about a month ago":"in about a month";var T=parseInt(g.date("Y",M),10),E=parseInt(g.date("Y",A),10),N=12*T+parseInt(g.date("n",M),10),o=12*E+parseInt(g.date("n",A),10),n=N-o;if(n<12&&n>-12)return n>=0?n+" months ago":"in "+-n+" months";var C=T-E;return C<2&&C>-2?C>=0?"a year ago":"in a year":C>=0?C+" years ago":"in "+-C+" years"},g.ordinal=function(A){A=parseInt(A,10),A=isNaN(A)?0:A;var M=A<0?"-":"";A=Math.abs(A);var t=A%100;return M+A+(t>4&&t<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th")},g.filesize=function(A,M,t,I,e,i){return M=void 0===M?1024:M,A<=0?"0 bytes":(A

    "),A=A.replace(/\n/g,"
    "),"

    "+A+"

    "},g.nl2br=function(A){return A.replace(/(\r\n|\n|\r)/g,"
    ")},g.truncatechars=function(A,M){return A.length<=M?A:A.substr(0,M)+"…"},g.truncatewords=function(A,M){var t=A.split(" ");return t.length0,Q=C.enumErrorProps&&(A===u||A instanceof Error),r=C.enumPrototypes&&T(A);++IM.documentElement.clientHeight;return{modalStyles:{paddingRight:I&&!g?Q.default():void 0,paddingLeft:!I&&g?Q.default():void 0}}}});X.Body=z.default,X.Header=U.default,X.Title=m.default,X.Footer=f.default,X.Dialog=h.default,X.TRANSITION_DURATION=300,X.BACKDROP_TRANSITION_DURATION=150,M.default=c.bsSizes([a.Sizes.LARGE,a.Sizes.SMALL],c.bsClass("modal",X)),A.exports=M.default},function(A,M,t){"use strict";var I=t(15).default,g=t(14).default,e=t(38).default,i=t(7).default,T=t(6).default;M.__esModule=!0;var E=t(1),N=T(E),o=t(5),n=T(o),C=t(11),c=T(C),D=t(44),a=T(D),B=function(A){function M(){g(this,M),A.apply(this,arguments)}return I(M,A),M.prototype.render=function(){var A=this.props,M=A["aria-label"],t=e(A,["aria-label"]),I=a.default(this.context.$bs_onModalHide,this.props.onHide);return N.default.createElement("div",i({},t,{className:n.default(this.props.className,c.default.prefix(this.props,"header"))}),this.props.closeButton&&N.default.createElement("button",{type:"button",className:"close","aria-label":M,onClick:I},N.default.createElement("span",{"aria-hidden":"true"},"×")),this.props.children)},M}(N.default.Component);B.propTypes={"aria-label":N.default.PropTypes.string, +bsClass:N.default.PropTypes.string,closeButton:N.default.PropTypes.bool,onHide:N.default.PropTypes.func},B.contextTypes={$bs_onModalHide:N.default.PropTypes.func},B.defaultProps={"aria-label":"Close",closeButton:!1},M.default=C.bsClass("modal",B),A.exports=M.default},function(A,M,t){"use strict";function I(A,M){return Array.isArray(M)?M.indexOf(A)>=0:A===M}var g=t(7).default,e=t(78).default,i=t(6).default;M.__esModule=!0;var T=t(40),E=i(T),N=t(170),o=i(N),n=t(1),C=i(n),c=t(16),D=i(c),a=t(127),B=(i(a),t(370)),Q=i(B),r=t(44),s=i(r),x=C.default.createClass({displayName:"OverlayTrigger",propTypes:g({},Q.default.propTypes,{trigger:C.default.PropTypes.oneOfType([C.default.PropTypes.oneOf(["click","hover","focus"]),C.default.PropTypes.arrayOf(C.default.PropTypes.oneOf(["click","hover","focus"]))]),delay:C.default.PropTypes.number,delayShow:C.default.PropTypes.number,delayHide:C.default.PropTypes.number,defaultOverlayShown:C.default.PropTypes.bool,overlay:C.default.PropTypes.node.isRequired,onBlur:C.default.PropTypes.func,onClick:C.default.PropTypes.func,onFocus:C.default.PropTypes.func,onMouseEnter:C.default.PropTypes.func,onMouseLeave:C.default.PropTypes.func,target:function(){},onHide:function(){},show:function(){}}),getDefaultProps:function(){return{defaultOverlayShown:!1,trigger:["hover","focus"]}},getInitialState:function(){return{isOverlayShown:this.props.defaultOverlayShown}},show:function(){this.setState({isOverlayShown:!0})},hide:function(){this.setState({isOverlayShown:!1})},toggle:function(){this.state.isOverlayShown?this.hide():this.show()},componentWillMount:function(){this.handleMouseOver=this.handleMouseOverOut.bind(null,this.handleDelayedShow),this.handleMouseOut=this.handleMouseOverOut.bind(null,this.handleDelayedHide)},componentDidMount:function(){this._mountNode=document.createElement("div"),this.renderOverlay()},renderOverlay:function(){D.default.unstable_renderSubtreeIntoContainer(this,this._overlay,this._mountNode)},componentWillUnmount:function(){D.default.unmountComponentAtNode(this._mountNode),this._mountNode=null,clearTimeout(this._hoverShowDelay),clearTimeout(this._hoverHideDelay)},componentDidUpdate:function(){this._mountNode&&this.renderOverlay()},getOverlayTarget:function(){return D.default.findDOMNode(this)},getOverlay:function(){var A=g({},o.default(this.props,e(Q.default.propTypes)),{show:this.state.isOverlayShown,onHide:this.hide,target:this.getOverlayTarget,onExit:this.props.onExit,onExiting:this.props.onExiting,onExited:this.props.onExited,onEnter:this.props.onEnter,onEntering:this.props.onEntering,onEntered:this.props.onEntered}),M=n.cloneElement(this.props.overlay,{placement:A.placement,container:A.container});return C.default.createElement(Q.default,A,M)},render:function(){var A=C.default.Children.only(this.props.children),M=A.props,t={"aria-describedby":this.props.overlay.props.id};return this._overlay=this.getOverlay(),t.onClick=s.default(M.onClick,this.props.onClick),I("click",this.props.trigger)&&(t.onClick=s.default(this.toggle,t.onClick)),I("hover",this.props.trigger)&&(t.onMouseOver=s.default(this.handleMouseOver,this.props.onMouseOver,M.onMouseOver),t.onMouseOut=s.default(this.handleMouseOut,this.props.onMouseOut,M.onMouseOut)),I("focus",this.props.trigger)&&(t.onFocus=s.default(this.handleDelayedShow,this.props.onFocus,M.onFocus),t.onBlur=s.default(this.handleDelayedHide,this.props.onBlur,M.onBlur)),n.cloneElement(A,t)},handleDelayedShow:function(){var A=this;if(null!=this._hoverHideDelay)return clearTimeout(this._hoverHideDelay),void(this._hoverHideDelay=null);if(!this.state.isOverlayShown&&null==this._hoverShowDelay){var M=null!=this.props.delayShow?this.props.delayShow:this.props.delay;return M?void(this._hoverShowDelay=setTimeout(function(){A._hoverShowDelay=null,A.show()},M)):void this.show()}},handleDelayedHide:function(){var A=this;if(null!=this._hoverShowDelay)return clearTimeout(this._hoverShowDelay),void(this._hoverShowDelay=null);if(this.state.isOverlayShown&&null==this._hoverHideDelay){var M=null!=this.props.delayHide?this.props.delayHide:this.props.delay;return M?void(this._hoverHideDelay=setTimeout(function(){A._hoverHideDelay=null,A.hide()},M)):void this.hide()}},handleMouseOverOut:function(A,M){var t=M.currentTarget,I=M.relatedTarget||M.nativeEvent.toElement;I&&(I===t||E.default(t,I))||A(M)}});M.default=x,A.exports=M.default},function(A,M,t){"use strict";var I=t(7).default,g=t(6).default;M.__esModule=!0;var e=t(1),i=g(e),T=t(5),E=g(T),N=t(11),o=g(N),n=t(183),C=g(n),c=i.default.createClass({displayName:"Tooltip",propTypes:{id:C.default(i.default.PropTypes.oneOfType([i.default.PropTypes.string,i.default.PropTypes.number])),placement:i.default.PropTypes.oneOf(["top","right","bottom","left"]),positionLeft:i.default.PropTypes.number,positionTop:i.default.PropTypes.number,arrowOffsetLeft:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),arrowOffsetTop:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),title:i.default.PropTypes.node},getDefaultProps:function(){return{bsClass:"tooltip",placement:"right"}},render:function(){var A,M=(A={},A[o.default.prefix(this.props)]=!0,A[this.props.placement]=!0,A),t=I({left:this.props.positionLeft,top:this.props.positionTop},this.props.style),g={left:this.props.arrowOffsetLeft,top:this.props.arrowOffsetTop};return i.default.createElement("div",I({role:"tooltip"},this.props,{className:E.default(this.props.className,M),style:t}),i.default.createElement("div",{className:o.default.prefix(this.props,"arrow"),style:g}),i.default.createElement("div",{className:o.default.prefix(this.props,"inner")},this.props.children))}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){return A="function"==typeof A?A():A,i.default.findDOMNode(A)||M}Object.defineProperty(M,"__esModule",{value:!0}),M.default=g;var e=t(16),i=I(e);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement. You can usually obtain a ReactComponent or DOMElement from a ReactElement by attaching a ref to it."):"object"===E&&"function"==typeof i.render||1===i.nodeType?null:new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement.")}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M,t){"use strict";function I(){function A(A,M,I){for(var g=0;g>",null!=t[I]?A(t,I,g):M?new Error("Required prop '"+I+"' was not specified in '"+g+"'."):void 0}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}M.__esModule=!0,M.errMsg=t,M.createChainableTypeChecker=I},function(A,M){"use strict";function t(A,M,t){function I(){return i=!0,T?void(N=[].concat(Array.prototype.slice.call(arguments))):void t.apply(this,arguments)}function g(){if(!i&&(E=!0,!T)){for(T=!0;!i&&e=A&&E&&(i=!0,t()))}}var e=0,i=!1,T=!1,E=!1,N=void 0;g()}function I(A,M,t){function I(A,M,I){i||(M?(i=!0,t(M)):(e[A]=I,i=++T===g,i&&t(null,e)))}var g=A.length,e=[];if(0===g)return t(null,e);var i=!1,T=0;A.forEach(function(A,t){M(A,t,function(A,M){I(t,A,M)})})}M.__esModule=!0,M.loopAsync=t,M.mapAsync=I},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0,M.router=M.routes=M.route=M.components=M.component=M.location=M.history=M.falsy=M.locationShape=M.routerShape=void 0;var e=t(1),i=t(66),T=(g(i),t(34)),E=I(T),N=t(9),o=(g(N),e.PropTypes.func),n=e.PropTypes.object,C=e.PropTypes.shape,c=e.PropTypes.string,D=M.routerShape=C({push:o.isRequired,replace:o.isRequired,go:o.isRequired,goBack:o.isRequired,goForward:o.isRequired,setRouteLeaveHook:o.isRequired,isActive:o.isRequired}),a=M.locationShape=C({pathname:c.isRequired,search:c.isRequired,state:n,action:c.isRequired,key:c}),B=M.falsy=E.falsy,Q=M.history=E.history,r=M.location=a,s=M.component=E.component,x=M.components=E.components,j=M.route=E.route,y=(M.routes=E.routes,M.router=D),u={falsy:B,history:Q,location:r,component:s,components:x,route:j,router:y};M.default=u},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!0;return!1}function e(A,M){function t(M){var t=!(arguments.length<=1||void 0===arguments[1])&&arguments[1],I=arguments.length<=2||void 0===arguments[2]?null:arguments[2],g=void 0;return t&&t!==!0||null!==I?(M={pathname:M,query:t},g=I||!1):(M=A.createLocation(M),g=t),(0,C.default)(M,g,s.location,s.routes,s.params)}function I(A,t){x&&x.location===A?e(x,t):(0,B.default)(M,A,function(M,I){M?t(M):I?e(i({},I,{location:A}),t):t()})}function e(A,M){function t(t,g){return t||g?I(t,g):void(0,D.default)(A,function(t,I){t?M(t):M(null,null,s=i({},A,{components:I}))})}function I(A,t){A?M(A):M(null,t)}var g=(0,N.default)(s,A),e=g.leaveRoutes,T=g.changeRoutes,E=g.enterRoutes;(0,o.runLeaveHooks)(e,s),e.filter(function(A){return E.indexOf(A)===-1}).forEach(a),(0,o.runChangeHooks)(T,s,A,function(M,g){return M||g?I(M,g):void(0,o.runEnterHooks)(E,A,t)})}function T(A){var M=arguments.length<=1||void 0===arguments[1]||arguments[1];return A.__id__||M&&(A.__id__=j++)}function E(A){return A.reduce(function(A,M){return A.push.apply(A,y[T(M)]),A},[])}function n(A,t){(0,B.default)(M,A,function(M,I){if(null==I)return void t();x=i({},I,{location:A});for(var g=E((0,N.default)(s,x).leaveRoutes),e=void 0,T=0,o=g.length;null==e&&T=32||13===M?M:0}A.exports=t},function(A,M){"use strict";function t(A){var M=this,t=M.nativeEvent;if(t.getModifierState)return t.getModifierState(A);var I=g[A];return!!I&&!!t[I]}function I(A){return t}var g={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};A.exports=I},function(A,M){"use strict";function t(A){var M=A.target||A.srcElement||window;return 3===M.nodeType?M.parentNode:M}A.exports=t},function(A,M){"use strict";function t(A){var M=A&&(I&&A[I]||A[g]);if("function"==typeof M)return M}var I="function"==typeof Symbol&&Symbol.iterator,g="@@iterator";A.exports=t},function(A,M,t){"use strict";function I(A){return"function"==typeof A&&"undefined"!=typeof A.prototype&&"function"==typeof A.prototype.mountComponent&&"function"==typeof A.prototype.receiveComponent}function g(A){var M;if(null===A||A===!1)M=new i(g);else if("object"==typeof A){var t=A;!t||"function"!=typeof t.type&&"string"!=typeof t.type?N(!1):void 0,M="string"==typeof t.type?T.createInternalComponent(t):I(t.type)?new t.type(t):new o}else"string"==typeof A||"number"==typeof A?M=T.createInstanceForText(A):N(!1);return M.construct(A),M._mountIndex=0,M._mountImage=null,M}var e=t(443),i=t(215),T=t(221),E=t(4),N=t(2),o=(t(3),function(){});E(o.prototype,e.Mixin,{_instantiateReactComponent:g}),A.exports=g},function(A,M,t){"use strict";/** * Checks if an event is supported in the current execution environment. * * NOTE: This will not work correctly for non-generic events such as ` + "`" + `change` + "`" + `, @@ -200,21 +200,21 @@ propTypes:g({},Q.default.propTypes,{trigger:C.default.PropTypes.oneOfType([C.def * @internal * @license Modernizr 3.0.0pre (Custom Build) | MIT */ -function I(A,M){if(!e.canUseDOM||M&&!("addEventListener"in document))return!1;var t="on"+A,I=t in document;if(!I){var i=document.createElement("div");i.setAttribute(t,"return;"),I="function"==typeof i[t]}return!I&&g&&"wheel"===A&&(I=document.implementation.hasFeature("Events.wheel","3.0")),I}var g,e=t(10);e.canUseDOM&&(g=document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("","")!==!0),A.exports=I},function(A,M,t){"use strict";var I=t(10),g=t(75),e=t(76),i=function(A,M){A.textContent=M};I.canUseDOM&&("textContent"in document.documentElement||(i=function(A,M){e(A,g(M))})),A.exports=i},function(A,M){"use strict";function t(A,M){var t=null===A||A===!1,I=null===M||M===!1;if(t||I)return t===I;var g=typeof A,e=typeof M;return"string"===g||"number"===g?"string"===e||"number"===e:"object"===e&&A.type===M.type&&A.key===M.key}A.exports=t},function(A,M,t){"use strict";function I(A){return a[A]}function g(A,M){return A&&null!=A.key?i(A.key):M.toString(36)}function e(A){return(""+A).replace(B,I)}function i(A){return"$"+e(A)}function T(A,M,t,I){var e=typeof A;if("undefined"!==e&&"boolean"!==e||(A=null),null===A||"string"===e||"number"===e||N.isValidElement(A))return t(I,A,""===M?c+g(A,0):M),1;var E,o,a=0,B=""===M?c:M+D;if(Array.isArray(A))for(var Q=0;QM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;iM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;i-1&&A%1==0&&A1)for(var t=1;tA.clientHeight}Object.defineProperty(M,"__esModule",{value:!0}),M.default=i;var T=t(57),E=I(T),N=t(39),o=I(N);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):"function"!==E&&"string"!==E?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):null}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M){"use strict";function t(A){function M(M,t,I,g,e,i){var T=g||"<>",E=i||I;if(null==t[I])return M?new Error("Required "+e+" ` + "`" + `"+E+"` + "`" + ` was not specified "+("in ` + "`" + `"+T+"` + "`" + `.")):null;for(var N=arguments.length,o=Array(N>6?N-6:0),n=6;n=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return 0===A.button}function i(A){return!!(A.metaKey||A.altKey||A.ctrlKey||A.shiftKey)}function T(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!1;return!0}function E(A,M){var t=M.query,I=M.hash,g=M.state;return t||I||g?{pathname:A,query:t,hash:I,state:g}:A}M.__esModule=!0;var N=Object.assign||function(A){for(var M=1;M=0;I--){var g=A[I],e=g.path||"";if(t=e.replace(/\/*$/,"/")+t,0===e.indexOf("/"))break}return"/"+t}},propTypes:{path:C,from:C,to:C.isRequired,query:c,state:c,onEnter:o.falsy,children:o.falsy},render:function(){(0,T.default)(!1)}});M.default=D,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0;var g=t(1),e=I(g),i=t(8),T=I(i),E=t(30),N=t(34),o=e.default.PropTypes,n=o.string,C=o.func,c=e.default.createClass({displayName:"Route",statics:{createRouteFromReactElement:E.createRouteFromReactElement},propTypes:{path:n,component:N.component,components:N.components,getComponent:C,getComponents:C},render:function(){(0,T.default)(!1)}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return!A||!A.__v2_compatible__}function i(A){return A&&A.getCurrentLocation}M.__esModule=!0;var T=Object.assign||function(A){for(var M=1;M=0&&0===window.sessionStorage.length)return;throw A}}function i(A){var M=void 0;try{M=window.sessionStorage.getItem(g(A))}catch(A){if(A.name===o)return null}if(M)try{return JSON.parse(M)}catch(A){}return null}M.__esModule=!0,M.saveState=e,M.readState=i;var T=t(23),E=(I(T),"@@History/"),N=["QuotaExceededError","QUOTA_EXCEEDED_ERR"],o="SecurityError"},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){function M(A){return E.canUseDOM?void 0:T.default(!1),t.listen(A)}var t=n.default(e({getUserConfirmation:N.getUserConfirmation},A,{go:N.go}));return e({},t,{listen:M})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M1?M-1:0),e=1;e=A.childNodes.length?null:A.childNodes.item(t);A.insertBefore(M,I)}var g=t(433),e=t(220),i=t(17),T=t(76),E=t(121),N=t(2),o={dangerouslyReplaceNodeWithMarkup:g.dangerouslyReplaceNodeWithMarkup,updateTextContent:E,processUpdates:function(A,M){for(var t,i=null,o=null,n=0;n-1?void 0:i(!1),!N.plugins[t]){M.extractEvents?void 0:i(!1),N.plugins[t]=M;var I=M.eventTypes;for(var e in I)g(I[e],M,e)?void 0:i(!1)}}}function g(A,M,t){N.eventNameDispatchConfigs.hasOwnProperty(t)?i(!1):void 0,N.eventNameDispatchConfigs[t]=A;var I=A.phasedRegistrationNames;if(I){for(var g in I)if(I.hasOwnProperty(g)){var T=I[g];e(T,M,t)}return!0}return!!A.registrationName&&(e(A.registrationName,M,t),!0)}function e(A,M,t){N.registrationNameModules[A]?i(!1):void 0,N.registrationNameModules[A]=M,N.registrationNameDependencies[A]=M.eventTypes[t].dependencies}var i=t(2),T=null,E={},N={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(A){T?i(!1):void 0,T=Array.prototype.slice.call(A),I()},injectEventPluginsByName:function(A){var M=!1;for(var t in A)if(A.hasOwnProperty(t)){var g=A[t];E.hasOwnProperty(t)&&E[t]===g||(E[t]?i(!1):void 0,E[t]=g,M=!0)}M&&I()},getPluginModuleForEvent:function(A){var M=A.dispatchConfig;if(M.registrationName)return N.registrationNameModules[M.registrationName]||null;for(var t in M.phasedRegistrationNames)if(M.phasedRegistrationNames.hasOwnProperty(t)){var I=N.registrationNameModules[M.phasedRegistrationNames[t]];if(I)return I}return null},_resetEventPlugins:function(){T=null;for(var A in E)E.hasOwnProperty(A)&&delete E[A];N.plugins.length=0;var M=N.eventNameDispatchConfigs;for(var t in M)M.hasOwnProperty(t)&&delete M[t];var I=N.registrationNameModules;for(var g in I)I.hasOwnProperty(g)&&delete I[g]}};A.exports=N},function(A,M,t){"use strict";function I(A){return(""+A).replace(x,"//")}function g(A,M){this.func=A,this.context=M,this.count=0}function e(A,M,t){var I=A.func,g=A.context;I.call(g,M,A.count++)}function i(A,M,t){if(null==A)return A;var I=g.getPooled(M,t);Q(A,e,I),g.release(I)}function T(A,M,t,I){this.result=A,this.keyPrefix=M,this.func=t,this.context=I,this.count=0}function E(A,M,t){var g=A.result,e=A.keyPrefix,i=A.func,T=A.context,E=i.call(T,M,A.count++);Array.isArray(E)?N(E,g,t,B.thatReturnsArgument):null!=E&&(a.isValidElement(E)&&(E=a.cloneAndReplaceKey(E,e+(E!==M?I(E.key||"")+"/":"")+t)),g.push(E))}function N(A,M,t,g,e){var i="";null!=t&&(i=I(t)+"/");var N=T.getPooled(M,i,g,e);Q(A,E,N),T.release(N)}function o(A,M,t){if(null==A)return A;var I=[];return N(A,I,null,M,t),I}function n(A,M,t){return null}function C(A,M){return Q(A,n,null)}function c(A){var M=[];return N(A,M,null,B.thatReturnsArgument),M}var D=t(31),a=t(13),B=t(20),Q=t(123),r=D.twoArgumentPooler,s=D.fourArgumentPooler,x=/\/(?!\/)/g;g.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},D.addPoolingTo(g,r),T.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},D.addPoolingTo(T,s);var j={forEach:i,map:o,mapIntoWithKeyPrefixInternal:N,count:C,toArray:c};A.exports=j},function(A,M,t){"use strict";function I(A,M){var t=y.hasOwnProperty(M)?y[M]:null;w.hasOwnProperty(M)&&(t!==x.OVERRIDE_BASE?B(!1):void 0),A.hasOwnProperty(M)&&(t!==x.DEFINE_MANY&&t!==x.DEFINE_MANY_MERGED?B(!1):void 0)}function g(A,M){if(M){"function"==typeof M?B(!1):void 0,C.isValidElement(M)?B(!1):void 0;var t=A.prototype;M.hasOwnProperty(s)&&u.mixins(A,M.mixins);for(var g in M)if(M.hasOwnProperty(g)&&g!==s){var e=M[g];if(I(t,g),u.hasOwnProperty(g))u[g](A,e);else{var i=y.hasOwnProperty(g),N=t.hasOwnProperty(g),o="function"==typeof e,n=o&&!i&&!N&&M.autobind!==!1;if(n)t.__reactAutoBindMap||(t.__reactAutoBindMap={}),t.__reactAutoBindMap[g]=e,t[g]=e;else if(N){var c=y[g];!i||c!==x.DEFINE_MANY_MERGED&&c!==x.DEFINE_MANY?B(!1):void 0,c===x.DEFINE_MANY_MERGED?t[g]=T(t[g],e):c===x.DEFINE_MANY&&(t[g]=E(t[g],e))}else t[g]=e}}}}function e(A,M){if(M)for(var t in M){var I=M[t];if(M.hasOwnProperty(t)){var g=t in u;g?B(!1):void 0;var e=t in A;e?B(!1):void 0,A[t]=I}}}function i(A,M){A&&M&&"object"==typeof A&&"object"==typeof M?void 0:B(!1);for(var t in M)M.hasOwnProperty(t)&&(void 0!==A[t]?B(!1):void 0,A[t]=M[t]);return A}function T(A,M){return function(){var t=A.apply(this,arguments),I=M.apply(this,arguments);if(null==t)return I;if(null==I)return t;var g={};return i(g,t),i(g,I),g}}function E(A,M){return function(){A.apply(this,arguments),M.apply(this,arguments)}}function N(A,M){var t=M.bind(A);return t}function o(A){for(var M in A.__reactAutoBindMap)if(A.__reactAutoBindMap.hasOwnProperty(M)){var t=A.__reactAutoBindMap[M];A[M]=N(A,t)}}var n=t(207),C=t(13),c=(t(71),t(70),t(222)),D=t(4),a=t(50),B=t(2),Q=t(59),r=t(27),s=(t(3),r({mixins:null})),x=Q({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),j=[],y={mixins:x.DEFINE_MANY,statics:x.DEFINE_MANY,propTypes:x.DEFINE_MANY,contextTypes:x.DEFINE_MANY,childContextTypes:x.DEFINE_MANY,getDefaultProps:x.DEFINE_MANY_MERGED,getInitialState:x.DEFINE_MANY_MERGED,getChildContext:x.DEFINE_MANY_MERGED,render:x.DEFINE_ONCE,componentWillMount:x.DEFINE_MANY,componentDidMount:x.DEFINE_MANY,componentWillReceiveProps:x.DEFINE_MANY,shouldComponentUpdate:x.DEFINE_ONCE,componentWillUpdate:x.DEFINE_MANY,componentDidUpdate:x.DEFINE_MANY,componentWillUnmount:x.DEFINE_MANY,updateComponent:x.OVERRIDE_BASE},u={displayName:function(A,M){A.displayName=M},mixins:function(A,M){if(M)for(var t=0;t"+T+""},receiveComponent:function(A,M){if(A!==this._currentElement){this._currentElement=A;var t=""+A;if(t!==this._stringText){this._stringText=t;var g=i.getNode(this._rootNodeID);I.updateTextContent(g,t)}}},unmountComponent:function(){e.unmountIDFromEnvironment(this._rootNodeID)}}),A.exports=o},function(A,M,t){"use strict";function I(){this.reinitializeTransaction()}var g=t(18),e=t(73),i=t(4),T=t(20),E={initialize:T,close:function(){C.isBatchingUpdates=!1}},N={initialize:T,close:g.flushBatchedUpdates.bind(g)},o=[N,E];i(I.prototype,e.Mixin,{getTransactionWrappers:function(){return o}});var n=new I,C={isBatchingUpdates:!1,batchedUpdates:function(A,M,t,I,g,e){var i=C.isBatchingUpdates;C.isBatchingUpdates=!0,i?A(M,t,I,g,e):n.perform(A,null,M,t,I,g,e)}};A.exports=C},function(A,M,t){"use strict";function I(){if(!L){L=!0,Q.EventEmitter.injectReactEventListener(B),Q.EventPluginHub.injectEventPluginOrder(T),Q.EventPluginHub.injectInstanceHandle(r),Q.EventPluginHub.injectMount(s),Q.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:u,EnterLeaveEventPlugin:E,ChangeEventPlugin:e,SelectEventPlugin:j,BeforeInputEventPlugin:g}),Q.NativeComponent.injectGenericComponentClass(D),Q.NativeComponent.injectTextComponentClass(a),Q.Class.injectMixin(n),Q.DOMProperty.injectDOMPropertyConfig(o),Q.DOMProperty.injectDOMPropertyConfig(w),Q.EmptyComponent.injectEmptyComponent("noscript"),Q.Updates.injectReconcileTransaction(x),Q.Updates.injectBatchingStrategy(c),Q.RootIndex.injectCreateReactRootIndex(N.canUseDOM?i.createReactRootIndex:y.createReactRootIndex),Q.Component.injectEnvironment(C)}}var g=t(429),e=t(431),i=t(432),T=t(434),E=t(435),N=t(10),o=t(438),n=t(440),C=t(109),c=t(212),D=t(444),a=t(211),B=t(452),Q=t(453),r=t(48),s=t(12),x=t(457),j=t(463),y=t(464),u=t(465),w=t(462),L=!1;A.exports={inject:I}},function(A,M,t){"use strict";function I(){if(n.current){var A=n.current.getName();if(A)return" Check the render method of ` + "`" + `"+A+"` + "`" + `."}return""}function g(A,M){if(A._store&&!A._store.validated&&null==A.key){A._store.validated=!0;e("uniqueKey",A,M)}}function e(A,M,t){var g=I();if(!g){var e="string"==typeof t?t:t.displayName||t.name;e&&(g=" Check the top-level render call using <"+e+">.")}var i=D[A]||(D[A]={});if(i[g])return null;i[g]=!0;var T={parentOrOwner:g,url:" See https://fb.me/react-warning-keys for more information.",childOwner:null};return M&&M._owner&&M._owner!==n.current&&(T.childOwner=" It was passed a child from "+M._owner.getName()+"."),T}function i(A,M){if("object"==typeof A)if(Array.isArray(A))for(var t=0;t/,e={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(A){var M=I(A);return A.replace(g," "+e.CHECKSUM_ATTR_NAME+'="'+M+'"$&')},canReuseMarkup:function(A,M){var t=M.getAttribute(e.CHECKSUM_ATTR_NAME);t=t&&parseInt(t,10);var g=I(A);return g===t}};A.exports=e},function(A,M,t){"use strict";var I=t(59),g=I({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOVE_NODE:null,SET_MARKUP:null,TEXT_CONTENT:null});A.exports=g},function(A,M,t){"use strict";function I(A){if("function"==typeof A.type)return A.type;var M=A.type,t=n[M];return null==t&&(n[M]=t=N(M)),t}function g(A){return o?void 0:E(!1),new o(A.type,A.props)}function e(A){return new C(A)}function i(A){return A instanceof C}var T=t(4),E=t(2),N=null,o=null,n={},C=null,c={injectGenericComponentClass:function(A){o=A},injectTextComponentClass:function(A){C=A},injectComponentClasses:function(A){T(n,A)}},D={getComponentClassForElement:I,createInternalComponent:g,createInstanceForText:e,isTextComponent:i,injection:c};A.exports=D},function(A,M,t){"use strict";function I(A,M){}var g=(t(3),{isMounted:function(A){return!1},enqueueCallback:function(A,M){},enqueueForceUpdate:function(A){I(A,"forceUpdate")},enqueueReplaceState:function(A,M){I(A,"replaceState")},enqueueSetState:function(A,M){I(A,"setState")},enqueueSetProps:function(A,M){I(A,"setProps")},enqueueReplaceProps:function(A,M){I(A,"replaceProps")}});A.exports=g},function(A,M,t){"use strict";function I(A){function M(M,t,I,g,e,i){if(g=g||y,i=i||I,null==t[I]){var T=s[e];return M?new Error("Required "+T+" ` + "`" + `"+i+"` + "`" + ` was not specified in "+("` + "`" + `"+g+"` + "`" + `.")):null}return A(t,I,g,e,i)}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}function g(A){function M(M,t,I,g,e){var i=M[t],T=a(i);if(T!==A){var E=s[g],N=B(i);return new Error("Invalid "+E+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+N+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected ")+("` + "`" + `"+A+"` + "`" + `."))}return null}return I(M)}function e(){return I(x.thatReturns(null))}function i(A){function M(M,t,I,g,e){var i=M[t];if(!Array.isArray(i)){var T=s[g],E=a(i);return new Error("Invalid "+T+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+E+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected an array."))}for(var N=0;N>"}var r=t(13),s=t(70),x=t(20),j=t(118),y="<>",u={array:g("array"),bool:g("boolean"),func:g("function"),number:g("number"),object:g("object"),string:g("string"),any:e(),arrayOf:i,element:T(),instanceOf:E,node:C(),objectOf:o,oneOf:N,oneOfType:n,shape:c};A.exports=u},function(A,M){"use strict";var t={injectCreateReactRootIndex:function(A){I.createReactRootIndex=A}},I={createReactRootIndex:null,injection:t};A.exports=I},function(A,M){"use strict";var t={currentScrollLeft:0,currentScrollTop:0,refreshScrollValues:function(A){t.currentScrollLeft=A.x,t.currentScrollTop=A.y}};A.exports=t},function(A,M,t){"use strict";function I(A,M){if(null==M?g(!1):void 0,null==A)return M;var t=Array.isArray(A),I=Array.isArray(M);return t&&I?(A.push.apply(A,M),A):t?(A.push(M),A):I?[A].concat(M):[A,M]}var g=t(2);A.exports=I},function(A,M){"use strict";var t=function(A,M,t){Array.isArray(A)?A.forEach(M,t):A&&M.call(t,A)};A.exports=t},function(A,M,t){"use strict";function I(){return!e&&g.canUseDOM&&(e="textContent"in document.documentElement?"textContent":"innerText"),e}var g=t(10),e=null;A.exports=I},function(A,M){"use strict";function t(A){var M=A&&A.nodeName&&A.nodeName.toLowerCase();return M&&("input"===M&&I[A.type]||"textarea"===M)}var I={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};A.exports=t},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(){for(var A=arguments.length,M=Array(A),t=0;t=0&&s.splice(M,1)}function T(A){var M=document.createElement("style");return M.type="text/css",e(A,M),M}function E(A){var M=document.createElement("link");return M.rel="stylesheet",e(A,M),M}function N(A,M){var t,I,g;if(M.singleton){var e=r++;t=Q||(Q=T(M)),I=o.bind(null,t,e,!1),g=o.bind(null,t,e,!0)}else A.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(t=E(M),I=C.bind(null,t),g=function(){i(t),t.href&&URL.revokeObjectURL(t.href)}):(t=T(M),I=n.bind(null,t),g=function(){i(t)});return I(A),function(M){if(M){if(M.css===A.css&&M.media===A.media&&M.sourceMap===A.sourceMap)return;I(A=M)}else g()}}function o(A,M,t,I){var g=t?"":I.css;if(A.styleSheet)A.styleSheet.cssText=x(M,g);else{var e=document.createTextNode(g),i=A.childNodes;i[M]&&A.removeChild(i[M]),i.length?A.insertBefore(e,i[M]):A.appendChild(e)}}function n(A,M){var t=M.css,I=M.media;if(I&&A.setAttribute("media",I),A.styleSheet)A.styleSheet.cssText=t;else{for(;A.firstChild;)A.removeChild(A.firstChild);A.appendChild(document.createTextNode(t))}}function C(A,M){var t=M.css,I=M.sourceMap;I&&(t+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(I))))+" */");var g=new Blob([t],{type:"text/css"}),e=A.href;A.href=URL.createObjectURL(g),e&&URL.revokeObjectURL(e)}var c={},D=function(A){var M;return function(){return"undefined"==typeof M&&(M=A.apply(this,arguments)),M}},a=D(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),B=D(function(){return document.head||document.getElementsByTagName("head")[0]}),Q=null,r=0,s=[];A.exports=function(A,M){M=M||{},"undefined"==typeof M.singleton&&(M.singleton=a()),"undefined"==typeof M.insertAt&&(M.insertAt="bottom");var t=g(A);return I(t,M),function(A){for(var e=[],i=0;i",'"',"` + "`" + `"," ","\r","\n","\t"],D=["{","}","|","\\","^","` + "`" + `"].concat(c),a=["'"].concat(D),B=["%","/","?",";","#"].concat(a),Q=["/","?","#"],r=255,s=/^[+a-z0-9A-Z_-]{0,63}$/,x=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,j={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},u={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=t(360);I.prototype.parse=function(A,M,t){if(!N.isString(A))throw new TypeError("Parameter 'url' must be a string, not "+typeof A);var I=A.indexOf("?"),g=I!==-1&&I127?"x":O[F];if(!m.match(s)){var k=U.slice(0,Y),R=U.slice(Y+1),J=O.match(x);J&&(k.push(J[1]),R.unshift(J[2])),R.length&&(T="/"+R.join(".")+T),this.hostname=k.join(".");break}}}this.hostname.length>r?this.hostname="":this.hostname=this.hostname.toLowerCase(),z||(this.hostname=E.toASCII(this.hostname));var G=this.port?":"+this.port:"",H=this.hostname||"";this.host=H+G,this.href+=this.host,z&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==T[0]&&(T="/"+T))}if(!j[D])for(var Y=0,p=a.length;Y0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return t.search=A.search,t.query=A.query,N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!j.length)return t.pathname=null,t.search?t.path="/"+t.search:t.path=null,t.href=t.format(),t;for(var l=j.slice(-1)[0],Y=(t.host||A.host||j.length>1)&&("."===l||".."===l)||""===l,d=0,h=j.length;h>=0;h--)l=j[h],"."===l?j.splice(h,1):".."===l?(j.splice(h,1),d++):d&&(j.splice(h,1),d--);if(!s&&!x)for(;d--;d)j.unshift("..");!s||""===j[0]||j[0]&&"/"===j[0].charAt(0)||j.unshift(""),Y&&"/"!==j.join("/").substr(-1)&&j.push("");var S=""===j[0]||j[0]&&"/"===j[0].charAt(0);if(w){t.hostname=t.host=S?"":j.length?j.shift():"";var L=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return s=s||t.host&&j.length,s&&!S&&j.unshift(""),j.length?t.pathname=j.join("/"):(t.pathname=null,t.path=null),N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=A.auth||t.auth,t.slashes=t.slashes||A.slashes,t.href=t.format(),t},I.prototype.parseHost=function(){var A=this.host,M=n.exec(A);M&&(M=M[0],":"!==M&&(this.port=M.substr(1)),A=A.substr(0,A.length-M.length)),A&&(this.hostname=A)}},function(A,M){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};A.exports=function(A,M){return"number"!=typeof M||t[A]?M:M+"px"}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M,t){return P.LoggedIn()?t():(location.pathname!==z.minioBrowserPrefix&&location.pathname!==z.minioBrowserPrefix+"/"||M(z.minioBrowserPrefix+"/login"),t())}function i(A,M){P.LoggedIn()&&M(""+z.minioBrowserPrefix)}function T(){q<2&&setTimeout(function(){document.querySelector(".page-load").classList.add("pl-"+q),q++,T()},K[q])}t(498);var E=t(1),N=g(E),o=t(16),n=g(o),C=t(484),c=g(C),D=t(125),a=g(D),B=t(230),Q=g(B),r=t(190),s=g(r),x=t(191),j=g(x),y=t(65),u=g(y),w=t(187),L=g(w),l=t(393),Y=g(l),d=t(22),h=g(d),S=t(42),z=(g(S),t(26)),U=t(19),p=I(U),O=t(255),m=g(O),F=t(245),f=g(F),k=t(241),R=g(k),J=t(497),G=(g(J),t(131)),H=g(G),b=t(60),X=g(b);window.Web=H.default;var v=(0,Q.default)(c.default)(a.default)(m.default),W=(0,h.default)(function(A){return A})(R.default),V=(0,h.default)(function(A){return A})(f.default),P=new H.default(window.location.protocol+"//"+window.location.host+z.minioBrowserPrefix+"/webrpc",v.dispatch);window.web=P,v.dispatch(p.setWeb(P));var Z=function(A){return N.default.createElement("div",null,A.children)};n.default.render(N.default.createElement(Y.default,{store:v,web:P},N.default.createElement(j.default,{history:u.default},N.default.createElement(s.default,{path:"/",component:Z},N.default.createElement(s.default,{path:"minio",component:Z},N.default.createElement(L.default,{component:W,onEnter:e}),N.default.createElement(s.default,{path:"login",component:V,onEnter:i}),N.default.createElement(s.default,{path:":bucket",component:W,onEnter:e}),N.default.createElement(s.default,{path:":bucket/*",component:W,onEnter:e}))))),document.getElementById("root"));var K=[0,400],q=0;T(),X.default.getItem("newlyUpdated")&&(v.dispatch(p.showAlert({type:"success",message:"Updated to the latest UI Version."})),X.default.removeItem("newlyUpdated"))},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t-1})))}},{key:"selectPrefix",value:function(A,M){A.preventDefault();var t=this.props,I=(t.dispatch,t.currentPath),g=(t.web,t.currentBucket),e=encodeURI(M);if(M.endsWith("/")||""===M){if(M===I)return;D.default.push(TA.pathJoin(g,e))}else window.location=window.location.origin+"/minio/download/"+g+"/"+e+"?token="+DA.default.getItem("token")}},{key:"makeBucket",value:function(A){A.preventDefault();var M=this.refs.makeBucketRef.value;this.refs.makeBucketRef.value="";var t=this.props,I=t.web,g=t.dispatch;this.hideMakeBucketModal(),I.MakeBucket({bucketName:M}).then(function(){g(eA.addBucket(M)),g(eA.selectBucket(M))}).catch(function(A){return g(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideMakeBucketModal",value:function(){var A=this.props.dispatch;A(eA.hideMakeBucketModal())}},{key:"showMakeBucketModal",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showMakeBucketModal())}},{key:"showAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showAbout())}},{key:"hideAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAbout())}},{key:"showBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showBucketPolicy())}},{key:"hideBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideBucketPolicy())}},{key:"uploadFile",value:function(A){A.preventDefault();var M=this.props,t=M.dispatch,I=M.buckets;if(0===I.length)return void t(eA.showAlert({type:"danger",message:"Bucket needs to be created before trying to upload files."}));var g=A.target.files[0];A.target.value=null,this.xhr=new XMLHttpRequest,t(eA.uploadFile(g,this.xhr))}},{key:"removeObject",value:function(){var A=this,M=this.props,t=M.web,I=M.dispatch,g=M.currentPath,e=M.currentBucket,i=M.deleteConfirmation;t.RemoveObject({bucketName:e,objectName:i.object}).then(function(){A.hideDeleteConfirmation(),I(eA.selectPrefix(g))}).catch(function(A){return I(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideAlert",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAlert())}},{key:"showDeleteConfirmation",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.showDeleteConfirmation(M))}},{key:"hideDeleteConfirmation",value:function(){var A=this.props.dispatch;A(eA.hideDeleteConfirmation())}},{key:"shareObject",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.shareObject(M))}},{key:"hideShareObjectModal",value:function(){var A=this.props.dispatch;A(eA.hideShareObject())}},{key:"dataType",value:function(A,M){return NA.getDataType(A,M)}},{key:"sortObjectsByName",value:function(A){var M=this.props,t=M.dispatch,I=M.objects,g=M.sortNameOrder;t(eA.setObjects(TA.sortObjectsByName(I,!g))),t(eA.setSortNameOrder(!g))}},{key:"sortObjectsBySize",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortSizeOrder;M(eA.setObjects(TA.sortObjectsBySize(t,!I))),M(eA.setSortSizeOrder(!I))}},{key:"sortObjectsByDate",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortDateOrder;M(eA.setObjects(TA.sortObjectsByDate(t,!I))),M(eA.setSortDateOrder(!I))}},{key:"logout",value:function(A){var M=this.props.web;A.preventDefault(),M.Logout(),D.default.push(oA.minioBrowserPrefix+"/login")}},{key:"fullScreen",value:function(A){A.preventDefault();var M=document.documentElement;M.requestFullscreen&&M.requestFullscreen(),M.mozRequestFullScreen&&M.mozRequestFullScreen(),M.webkitRequestFullscreen&&M.webkitRequestFullscreen(),M.msRequestFullscreen&&M.msRequestFullscreen()}},{key:"toggleSidebar",value:function(A){this.props.dispatch(eA.setSidebarStatus(A))}},{key:"hideSidebar",value:function(A){var M=A||window.event,t=M.srcElement||M.target;3===t.nodeType&&(t=t.parentNode);var I=t.id;"feh-trigger"!==I&&this.props.dispatch(eA.setSidebarStatus(!1))}},{key:"showSettings",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showSettings())}},{key:"showMessage",value:function(){var A=this.props.dispatch;A(eA.showAlert({type:"success",message:"Link copied to clipboard!"})),this.hideShareObjectModal()}},{key:"selectTexts",value:function(){this.refs.copyTextInput.select()}},{key:"handleExpireValue",value:function(A,M){M===-1?this.refs[A].stepDown(1):this.refs[A].stepUp(1),7==this.refs.expireDays.value&&(this.refs.expireHours.value=0,this.refs.expireMins.value=0)}},{key:"render",value:function(){var A=this.props.storageInfo,M=A.total,t=A.free,I=this.props,g=I.showMakeBucketModal,e=I.alert,i=I.sortNameOrder,T=I.sortSizeOrder,E=I.sortDateOrder,N=I.showAbout,n=I.showBucketPolicy,c=this.props.serverInfo,D=c.version,a=c.memory,Q=c.platform,r=c.runtime,x=this.props.sidebarStatus,y=this.props.showSettings,w=this.props,l=w.policies,d=w.currentBucket,S=(w.currentPath,this.props.deleteConfirmation),U=this.props.shareObject,p=this.props,O=p.web,F=p.prefixWritable,k=y?o.default.createElement(V.default,null):o.default.createElement("noscript",null),J=o.default.createElement(L.default,{className:(0,C.default)({alert:!0,animated:!0,fadeInDown:e.show,fadeOutUp:!e.show}),bsStyle:e.type,onDismiss:this.hideAlert.bind(this)},o.default.createElement("div",{className:"text-center"},e.message));e.message||(J="");var H=(o.default.createElement(h.default,{id:"tt-sign-out"},"Sign out"),o.default.createElement(h.default,{id:"tt-upload-file"},"Upload file")),X=o.default.createElement(h.default,{id:"tt-create-bucket"},"Create bucket"),W="",P="",K="",_=M-t,AA=_/M*100+"%";O.LoggedIn()?P=o.default.createElement($.default,{fullScreenFunc:this.fullScreen.bind(this),aboutFunc:this.showAbout.bind(this),settingsFunc:this.showSettings.bind(this),logoutFunc:this.logout.bind(this)}):W=o.default.createElement("a",{className:"btn btn-danger",href:"/minio/login"},"Login"),O.LoggedIn()&&(K=o.default.createElement("div",{className:"feh-usage"},o.default.createElement("div",{className:"fehu-chart"},o.default.createElement("div",{style:{width:AA}})),o.default.createElement("ul",null,o.default.createElement("li",null,"Used:",B.default.filesize(M-t)),o.default.createElement("li",{className:"pull-right"},"Free:",B.default.filesize(M-_)))));var tA="";return O.LoggedIn()?tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," "))),o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-bucket",onClick:this.showMakeBucketModal.bind(this)},o.default.createElement("i",{className:"fa fa-hdd-o"}))))):F&&(tA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:H},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," ")))))),o.default.createElement("div",{className:(0,C.default)({"file-explorer":!0,toggled:x})},o.default.createElement(R.default,{searchBuckets:this.searchBuckets.bind(this),selectBucket:this.selectBucket.bind(this),clickOutside:this.hideSidebar.bind(this),showPolicy:this.showBucketPolicy.bind(this)}),o.default.createElement("div",{className:"fe-body"},o.default.createElement(m.default,null,J,o.default.createElement("header",{className:"fe-header-mobile hidden-lg hidden-md"},o.default.createElement("div",{id:"feh-trigger",className:"feh-trigger "+(0,C.default)({"feht-toggled":x}),onClick:this.toggleSidebar.bind(this,!x)},o.default.createElement("div",{className:"feht-lines"},o.default.createElement("div",{className:"top"}),o.default.createElement("div",{className:"center"}),o.default.createElement("div",{className:"bottom"}))),o.default.createElement("img",{className:"mh-logo",src:IA.default,alt:""})),o.default.createElement("header",{className:"fe-header"},o.default.createElement(G.default,{selectPrefix:this.selectPrefix.bind(this)}),K,o.default.createElement("ul",{className:"feh-actions"},o.default.createElement(b.default,null),W,P)),o.default.createElement("div",{className:"feb-container"},o.default.createElement("header",{className:"fesl-row","data-type":"folder"},o.default.createElement("div",{className:"fesl-item fi-name",onClick:this.sortObjectsByName.bind(this),"data-sort":"name"},"Name",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-alpha-desc":i,"fa-sort-alpha-asc":!i})})),o.default.createElement("div",{className:"fesl-item fi-size",onClick:this.sortObjectsBySize.bind(this),"data-sort":"size"},"Size",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-amount-desc":T,"fa-sort-amount-asc":!T})})),o.default.createElement("div",{className:"fesl-item fi-modified",onClick:this.sortObjectsByDate.bind(this),"data-sort":"last-modified"},"Last Modified",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-numeric-desc":E,"fa-sort-numeric-asc":!E})})),o.default.createElement("div",{className:"fesl-item fi-actions"}))),o.default.createElement("div",{className:"feb-container"},o.default.createElement(f.default,{dataType:this.dataType.bind(this),selectPrefix:this.selectPrefix.bind(this),showDeleteConfirmation:this.showDeleteConfirmation.bind(this),shareObject:this.shareObject.bind(this)})),o.default.createElement(v.default,null),tA,o.default.createElement(s.default,{className:"modal-create-bucket",bsSize:"small",animation:!1,show:g,onHide:this.hideMakeBucketModal.bind(this)},o.default.createElement("button",{className:"close close-alt",onClick:this.hideMakeBucketModal.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement(j.default,null,o.default.createElement("form",{onSubmit:this.makeBucket.bind(this)},o.default.createElement("div",{className:"input-group"},o.default.createElement("input",{className:"ig-text",type:"text",ref:"makeBucketRef",placeholder:"Bucket Name",autoFocus:!0}),o.default.createElement("i",{className:"ig-helpers"}))))),o.default.createElement(s.default,{className:"modal-about modal-dark",animation:!1,show:N,onHide:this.hideAbout.bind(this)},o.default.createElement("button",{className:"close",onClick:this.hideAbout.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement("div",{className:"ma-inner"},o.default.createElement("div",{className:"mai-item hidden-xs"},o.default.createElement("a",{href:"https://minio.io",target:"_blank"},o.default.createElement("img",{className:"maii-logo",src:IA.default,alt:""}))),o.default.createElement("div",{className:"mai-item"},o.default.createElement("ul",{className:"maii-list"},o.default.createElement("li",null,o.default.createElement("div",null,"Version"),o.default.createElement("small",null,D)),o.default.createElement("li",null,o.default.createElement("div",null,"Memory"),o.default.createElement("small",null,a)),o.default.createElement("li",null,o.default.createElement("div",null,"Platform"),o.default.createElement("small",null,Q)),o.default.createElement("li",null,o.default.createElement("div",null,"Runtime"),o.default.createElement("small",null,r)))))),o.default.createElement(s.default,{className:"modal-policy",animation:!1,show:n,onHide:this.hideBucketPolicy.bind(this)},o.default.createElement(u.default,null,"Bucket Policy (",d,")",o.default.createElement("button",{className:"close close-alt",onClick:this.hideBucketPolicy.bind(this)},o.default.createElement("span",null,"×"))),o.default.createElement("div",{className:"pm-body"},o.default.createElement(Z.default,{bucket:d}),l.map(function(A,M){return o.default.createElement(q.default,{key:M,prefix:A.prefix,policy:A.policy})}))),o.default.createElement(MA.default,{show:S.show,icon:"fa fa-exclamation-triangle mci-red",text:"Are you sure you want to delete?",sub:"This cannot be undone!",okText:"Delete",cancelText:"Cancel",okHandler:this.removeObject.bind(this),cancelHandler:this.hideDeleteConfirmation.bind(this)}),o.default.createElement(s.default,{show:U.show,animation:!1,onHide:this.hideShareObjectModal.bind(this),bsSize:"small"},o.default.createElement(u.default,null,"Share Object"),o.default.createElement(j.default,null,o.default.createElement("div",{className:"input-group copy-text"},o.default.createElement("label",null,"Shareable Link"),o.default.createElement("input",{type:"text",ref:"copyTextInput",readOnly:"readOnly",value:window.location.protocol+"//"+U.url,onClick:this.selectTexts.bind(this)})),o.default.createElement("div",{className:"input-group",style:{display:O.LoggedIn()?"block":"none"}},o.default.createElement("label",null,"Expires in"),o.default.createElement("div",{className:"set-expire"},o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireDays",1)}),o.default.createElement("div",{className:"set-expire-title"},"Days"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireDays",type:"number",min:0,max:7,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireDays",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireHours",1)}),o.default.createElement("div",{className:"set-expire-title"},"Hours"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireHours",type:"number",min:0,max:24,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireHours",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireMins",1)}),o.default.createElement("div",{className:"set-expire-title"},"Minutes"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireMins",type:"number",min:1,max:60,defaultValue:45})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireMins",-1)}))))),o.default.createElement("div",{className:"modal-footer"},o.default.createElement(CA.default,{text:U.url,onCopy:this.showMessage.bind(this)},o.default.createElement("button",{className:"btn btn-success"},"Copy Link")),o.default.createElement("button",{className:"btn btn-link",onClick:this.hideShareObjectModal.bind(this)},"Cancel"))),k)))}}]),M}(o.default.Component);M.default=aA},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(91),N=I(E),o=function(A){var M=A.fullScreenFunc,t=A.aboutFunc,I=A.settingsFunc,g=A.logoutFunc;return e.default.createElement("li",null,e.default.createElement(N.default,{pullRight:!0,id:"top-right-menu"},e.default.createElement(N.default.Toggle,{noCaret:!0},e.default.createElement("i",{className:"fa fa-reorder"})),e.default.createElement(N.default.Menu,{className:"dropdown-menu-right"},e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://github.com/minio/miniobrowser"},"Github ",e.default.createElement("i",{className:"fa fa-github"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:M},"Fullscreen ",e.default.createElement("i",{className:"fa fa-expand"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://docs.minio.io/"},"Documentation ",e.default.createElement("i",{className:"fa fa-book"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://slack.minio.io"},"Ask for help ",e.default.createElement("i",{className:"fa fa-question-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:t},"About ",e.default.createElement("i",{className:"fa fa-info-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:I},"Settings ",e.default.createElement("i",{className:"fa fa-cog"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:g},"Sign Out ",e.default.createElement("i",{className:"fa fa-sign-out"}))))))};M.default=(0,T.default)(function(A){return A})(o)},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(95),N=I(E),o=t(94),n=I(o),C=function(A){var M=A.latestUiVersion;return M===currentUiVersion?e.default.createElement("noscript",null):e.default.createElement("li",{className:"hidden-xs hidden-sm"},e.default.createElement("a",{href:""},e.default.createElement(n.default,{placement:"left",overlay:e.default.createElement(N.default,{id:"tt-version-update"},"New update available. Click to refresh.")}," ",e.default.createElement("i",{className:"fa fa-refresh"})," ")))};M.default=(0,T.default)(function(A){return{latestUiVersion:A.latestUiVersion}})(C)},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M; -}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{buckets:[],visibleBuckets:[],objects:[],storageInfo:{},serverInfo:{},currentBucket:"",currentPath:"",showMakeBucketModal:!1,uploads:{},alert:{show:!1,type:"danger",message:""},loginError:!1,sortNameOrder:!1,sortSizeOrder:!1,sortDateOrder:!1,latestUiVersion:currentUiVersion,sideBarActive:!1,loginRedirectPath:E.minioBrowserPrefix,settings:{accessKey:"",secretKey:"",secretKeyVisible:!1},showSettings:!1,policies:[],deleteConfirmation:{object:"",show:!1},shareObject:{show:!1,url:"",expiry:604800},prefixWritable:!1},M=arguments[1],t=Object.assign({},A);switch(M.type){case T.SET_WEB:t.web=M.web;break;case T.SET_BUCKETS:t.buckets=M.buckets;break;case T.ADD_BUCKET:t.buckets=[M.bucket].concat(e(t.buckets)),t.visibleBuckets=[M.bucket].concat(e(t.visibleBuckets));break;case T.SET_VISIBLE_BUCKETS:t.visibleBuckets=M.visibleBuckets;break;case T.SET_CURRENT_BUCKET:t.currentBucket=M.currentBucket;break;case T.SET_OBJECTS:t.objects=M.objects;break;case T.SET_CURRENT_PATH:t.currentPath=M.currentPath;break;case T.SET_STORAGE_INFO:t.storageInfo=M.storageInfo;break;case T.SET_SERVER_INFO:t.serverInfo=M.serverInfo;break;case T.SHOW_MAKEBUCKET_MODAL:t.showMakeBucketModal=M.showMakeBucketModal;break;case T.UPLOAD_PROGRESS:t.uploads=Object.assign({},t.uploads),t.uploads[M.slug].loaded=M.loaded;break;case T.ADD_UPLOAD:t.uploads=Object.assign({},t.uploads,g({},M.slug,{loaded:0,size:M.size,xhr:M.xhr,name:M.name}));break;case T.STOP_UPLOAD:t.uploads=Object.assign({},t.uploads),delete t.uploads[M.slug];break;case T.SET_ALERT:t.alert.alertTimeout&&clearTimeout(t.alert.alertTimeout),M.alert.show?t.alert=M.alert:t.alert=Object.assign({},t.alert,{show:!1});break;case T.SET_LOGIN_ERROR:t.loginError=!0;break;case T.SET_SHOW_ABORT_MODAL:t.showAbortModal=M.showAbortModal;break;case T.SHOW_ABOUT:t.showAbout=M.showAbout;break;case T.SET_SORT_NAME_ORDER:t.sortNameOrder=M.sortNameOrder;break;case T.SET_SORT_SIZE_ORDER:t.sortSizeOrder=M.sortSizeOrder;break;case T.SET_SORT_DATE_ORDER:t.sortDateOrder=M.sortDateOrder;break;case T.SET_LATEST_UI_VERSION:t.latestUiVersion=M.latestUiVersion;break;case T.SET_SIDEBAR_STATUS:t.sidebarStatus=M.sidebarStatus;break;case T.SET_LOGIN_REDIRECT_PATH:t.loginRedirectPath=M.path;case T.SET_LOAD_BUCKET:t.loadBucket=M.loadBucket;break;case T.SET_LOAD_PATH:t.loadPath=M.loadPath;break;case T.SHOW_SETTINGS:t.showSettings=M.showSettings;break;case T.SET_SETTINGS:t.settings=Object.assign({},t.settings,M.settings);break;case T.SHOW_BUCKET_POLICY:t.showBucketPolicy=M.showBucketPolicy;break;case T.SET_POLICIES:t.policies=M.policies;break;case T.DELETE_CONFIRMATION:t.deleteConfirmation=Object.assign({},M.payload);break;case T.SET_SHARE_OBJECT:t.shareObject=Object.assign({},M.shareObject);break;case T.SET_PREFIX_WRITABLE:t.prefixWritable=M.prefixWritable}return t}},function(A,M,t){A.exports={default:t(260),__esModule:!0}},function(A,M,t){t(270),A.exports=t(49).Object.assign},function(A,M,t){var I=t(80);A.exports=function(A,M){return I.create(A,M)}},function(A,M,t){t(271),A.exports=t(49).Object.keys},function(A,M,t){t(272),A.exports=t(49).Object.setPrototypeOf},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M,t){var I=t(136);A.exports=function(A){if(!I(A))throw TypeError(A+" is not an object!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(263);A.exports=Object("z").propertyIsEnumerable(0)?Object:function(A){return"String"==I(A)?A.split(""):Object(A)}},function(A,M,t){var I=t(80),g=t(137),e=t(266);A.exports=t(135)(function(){var A=Object.assign,M={},t={},I=Symbol(),g="abcdefghijklmnopqrst";return M[I]=7,g.split("").forEach(function(A){t[A]=A}),7!=A({},M)[I]||Object.keys(A({},t)).join("")!=g})?function(A,M){for(var t=g(A),i=arguments,T=i.length,E=1,N=I.getKeys,o=I.getSymbols,n=I.isEnum;T>E;)for(var C,c=e(i[E++]),D=o?N(c).concat(o(c)):N(c),a=D.length,B=0;a>B;)n.call(c,C=D[B++])&&(t[C]=c[C]);return t}:Object.assign},function(A,M,t){var I=t(79),g=t(49),e=t(135);A.exports=function(A,M){var t=(g.Object||{})[A]||Object[A],i={};i[A]=M(t),I(I.S+I.F*e(function(){t(1)}),"Object",i)}},function(A,M,t){var I=t(80).getDesc,g=t(136),e=t(262),i=function(A,M){if(e(A),!g(M)&&null!==M)throw TypeError(M+": can't set as prototype!")};A.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(A,M,g){try{g=t(134)(Function.call,I(Object.prototype,"__proto__").set,2),g(A,[]),M=!(A instanceof Array)}catch(A){M=!0}return function(A,t){return i(A,t),M?A.__proto__=t:g(A,t),A}}({},!1):void 0),check:i}},function(A,M,t){var I=t(79);I(I.S+I.F,"Object",{assign:t(267)})},function(A,M,t){var I=t(137);t(268)("keys",function(A){return function(M){return A(I(M))}})},function(A,M,t){var I=t(79);I(I.S,"Object",{setPrototypeOf:t(269).set})},function(A,M,t){function I(A){if(A)return g(A)}function g(A){for(var M in I.prototype)A[M]=I.prototype[M];return A}A.exports=I,I.prototype.on=I.prototype.addEventListener=function(A,M){return this._callbacks=this._callbacks||{},(this._callbacks["$"+A]=this._callbacks["$"+A]||[]).push(M), -this},I.prototype.once=function(A,M){function t(){this.off(A,t),M.apply(this,arguments)}return t.fn=M,this.on(A,t),this},I.prototype.off=I.prototype.removeListener=I.prototype.removeAllListeners=I.prototype.removeEventListener=function(A,M){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+A];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+A],this;for(var I,g=0;g-1&&A%1==0&&A1)for(var t=1;tA.clientHeight}Object.defineProperty(M,"__esModule",{value:!0}),M.default=i;var T=t(57),E=I(T),N=t(39),o=I(N);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):"function"!==E&&"string"!==E?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):null}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M){"use strict";function t(A){function M(M,t,I,g,e,i){var T=g||"<>",E=i||I;if(null==t[I])return M?new Error("Required "+e+" ` + "`" + `"+E+"` + "`" + ` was not specified "+("in ` + "`" + `"+T+"` + "`" + `.")):null;for(var N=arguments.length,o=Array(N>6?N-6:0),n=6;n=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return 0===A.button}function i(A){return!!(A.metaKey||A.altKey||A.ctrlKey||A.shiftKey)}function T(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!1;return!0}function E(A,M){var t=M.query,I=M.hash,g=M.state;return t||I||g?{pathname:A,query:t,hash:I,state:g}:A}M.__esModule=!0;var N=Object.assign||function(A){for(var M=1;M=0;I--){var g=A[I],e=g.path||"";if(t=e.replace(/\/*$/,"/")+t,0===e.indexOf("/"))break}return"/"+t}},propTypes:{path:C,from:C,to:C.isRequired,query:c,state:c,onEnter:o.falsy,children:o.falsy},render:function(){(0,T.default)(!1)}});M.default=D,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0;var g=t(1),e=I(g),i=t(8),T=I(i),E=t(30),N=t(34),o=e.default.PropTypes,n=o.string,C=o.func,c=e.default.createClass({displayName:"Route",statics:{createRouteFromReactElement:E.createRouteFromReactElement},propTypes:{path:n,component:N.component,components:N.components,getComponent:C,getComponents:C},render:function(){(0,T.default)(!1)}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return!A||!A.__v2_compatible__}function i(A){return A&&A.getCurrentLocation}M.__esModule=!0;var T=Object.assign||function(A){for(var M=1;M=0&&0===window.sessionStorage.length)return;throw A}}function i(A){var M=void 0;try{M=window.sessionStorage.getItem(g(A))}catch(A){if(A.name===o)return null}if(M)try{return JSON.parse(M)}catch(A){}return null}M.__esModule=!0,M.saveState=e,M.readState=i;var T=t(23),E=(I(T),"@@History/"),N=["QuotaExceededError","QUOTA_EXCEEDED_ERR"],o="SecurityError"},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){function M(A){return E.canUseDOM?void 0:T.default(!1),t.listen(A)}var t=n.default(e({getUserConfirmation:N.getUserConfirmation},A,{go:N.go}));return e({},t,{listen:M})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M1?M-1:0),e=1;e=A.childNodes.length?null:A.childNodes.item(t);A.insertBefore(M,I)}var g=t(434),e=t(220),i=t(17),T=t(76),E=t(121),N=t(2),o={dangerouslyReplaceNodeWithMarkup:g.dangerouslyReplaceNodeWithMarkup,updateTextContent:E,processUpdates:function(A,M){for(var t,i=null,o=null,n=0;n-1?void 0:i(!1),!N.plugins[t]){M.extractEvents?void 0:i(!1),N.plugins[t]=M;var I=M.eventTypes;for(var e in I)g(I[e],M,e)?void 0:i(!1)}}}function g(A,M,t){N.eventNameDispatchConfigs.hasOwnProperty(t)?i(!1):void 0,N.eventNameDispatchConfigs[t]=A;var I=A.phasedRegistrationNames;if(I){for(var g in I)if(I.hasOwnProperty(g)){var T=I[g];e(T,M,t)}return!0}return!!A.registrationName&&(e(A.registrationName,M,t),!0)}function e(A,M,t){N.registrationNameModules[A]?i(!1):void 0,N.registrationNameModules[A]=M,N.registrationNameDependencies[A]=M.eventTypes[t].dependencies}var i=t(2),T=null,E={},N={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(A){T?i(!1):void 0,T=Array.prototype.slice.call(A),I()},injectEventPluginsByName:function(A){var M=!1;for(var t in A)if(A.hasOwnProperty(t)){var g=A[t];E.hasOwnProperty(t)&&E[t]===g||(E[t]?i(!1):void 0,E[t]=g,M=!0)}M&&I()},getPluginModuleForEvent:function(A){var M=A.dispatchConfig;if(M.registrationName)return N.registrationNameModules[M.registrationName]||null;for(var t in M.phasedRegistrationNames)if(M.phasedRegistrationNames.hasOwnProperty(t)){var I=N.registrationNameModules[M.phasedRegistrationNames[t]];if(I)return I}return null},_resetEventPlugins:function(){T=null;for(var A in E)E.hasOwnProperty(A)&&delete E[A];N.plugins.length=0;var M=N.eventNameDispatchConfigs;for(var t in M)M.hasOwnProperty(t)&&delete M[t];var I=N.registrationNameModules;for(var g in I)I.hasOwnProperty(g)&&delete I[g]}};A.exports=N},function(A,M,t){"use strict";function I(A){return(""+A).replace(x,"//")}function g(A,M){this.func=A,this.context=M,this.count=0}function e(A,M,t){var I=A.func,g=A.context;I.call(g,M,A.count++)}function i(A,M,t){if(null==A)return A;var I=g.getPooled(M,t);Q(A,e,I),g.release(I)}function T(A,M,t,I){this.result=A,this.keyPrefix=M,this.func=t,this.context=I,this.count=0}function E(A,M,t){var g=A.result,e=A.keyPrefix,i=A.func,T=A.context,E=i.call(T,M,A.count++);Array.isArray(E)?N(E,g,t,B.thatReturnsArgument):null!=E&&(a.isValidElement(E)&&(E=a.cloneAndReplaceKey(E,e+(E!==M?I(E.key||"")+"/":"")+t)),g.push(E))}function N(A,M,t,g,e){var i="";null!=t&&(i=I(t)+"/");var N=T.getPooled(M,i,g,e);Q(A,E,N),T.release(N)}function o(A,M,t){if(null==A)return A;var I=[];return N(A,I,null,M,t),I}function n(A,M,t){return null}function C(A,M){return Q(A,n,null)}function c(A){var M=[];return N(A,M,null,B.thatReturnsArgument),M}var D=t(31),a=t(13),B=t(20),Q=t(123),r=D.twoArgumentPooler,s=D.fourArgumentPooler,x=/\/(?!\/)/g;g.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},D.addPoolingTo(g,r),T.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},D.addPoolingTo(T,s);var j={forEach:i,map:o,mapIntoWithKeyPrefixInternal:N,count:C,toArray:c};A.exports=j},function(A,M,t){"use strict";function I(A,M){var t=y.hasOwnProperty(M)?y[M]:null;w.hasOwnProperty(M)&&(t!==x.OVERRIDE_BASE?B(!1):void 0),A.hasOwnProperty(M)&&(t!==x.DEFINE_MANY&&t!==x.DEFINE_MANY_MERGED?B(!1):void 0)}function g(A,M){if(M){"function"==typeof M?B(!1):void 0,C.isValidElement(M)?B(!1):void 0;var t=A.prototype;M.hasOwnProperty(s)&&u.mixins(A,M.mixins);for(var g in M)if(M.hasOwnProperty(g)&&g!==s){var e=M[g];if(I(t,g),u.hasOwnProperty(g))u[g](A,e);else{var i=y.hasOwnProperty(g),N=t.hasOwnProperty(g),o="function"==typeof e,n=o&&!i&&!N&&M.autobind!==!1;if(n)t.__reactAutoBindMap||(t.__reactAutoBindMap={}),t.__reactAutoBindMap[g]=e,t[g]=e;else if(N){var c=y[g];!i||c!==x.DEFINE_MANY_MERGED&&c!==x.DEFINE_MANY?B(!1):void 0,c===x.DEFINE_MANY_MERGED?t[g]=T(t[g],e):c===x.DEFINE_MANY&&(t[g]=E(t[g],e))}else t[g]=e}}}}function e(A,M){if(M)for(var t in M){var I=M[t];if(M.hasOwnProperty(t)){var g=t in u;g?B(!1):void 0;var e=t in A;e?B(!1):void 0,A[t]=I}}}function i(A,M){A&&M&&"object"==typeof A&&"object"==typeof M?void 0:B(!1);for(var t in M)M.hasOwnProperty(t)&&(void 0!==A[t]?B(!1):void 0,A[t]=M[t]);return A}function T(A,M){return function(){var t=A.apply(this,arguments),I=M.apply(this,arguments);if(null==t)return I;if(null==I)return t;var g={};return i(g,t),i(g,I),g}}function E(A,M){return function(){A.apply(this,arguments),M.apply(this,arguments)}}function N(A,M){var t=M.bind(A);return t}function o(A){for(var M in A.__reactAutoBindMap)if(A.__reactAutoBindMap.hasOwnProperty(M)){var t=A.__reactAutoBindMap[M];A[M]=N(A,t)}}var n=t(207),C=t(13),c=(t(71),t(70),t(222)),D=t(4),a=t(50),B=t(2),Q=t(59),r=t(27),s=(t(3),r({mixins:null})),x=Q({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),j=[],y={mixins:x.DEFINE_MANY,statics:x.DEFINE_MANY,propTypes:x.DEFINE_MANY,contextTypes:x.DEFINE_MANY,childContextTypes:x.DEFINE_MANY,getDefaultProps:x.DEFINE_MANY_MERGED,getInitialState:x.DEFINE_MANY_MERGED,getChildContext:x.DEFINE_MANY_MERGED,render:x.DEFINE_ONCE,componentWillMount:x.DEFINE_MANY,componentDidMount:x.DEFINE_MANY,componentWillReceiveProps:x.DEFINE_MANY,shouldComponentUpdate:x.DEFINE_ONCE,componentWillUpdate:x.DEFINE_MANY,componentDidUpdate:x.DEFINE_MANY,componentWillUnmount:x.DEFINE_MANY,updateComponent:x.OVERRIDE_BASE},u={displayName:function(A,M){A.displayName=M},mixins:function(A,M){if(M)for(var t=0;t"+T+""},receiveComponent:function(A,M){if(A!==this._currentElement){this._currentElement=A;var t=""+A;if(t!==this._stringText){this._stringText=t;var g=i.getNode(this._rootNodeID);I.updateTextContent(g,t)}}},unmountComponent:function(){e.unmountIDFromEnvironment(this._rootNodeID)}}),A.exports=o},function(A,M,t){"use strict";function I(){this.reinitializeTransaction()}var g=t(18),e=t(73),i=t(4),T=t(20),E={initialize:T,close:function(){C.isBatchingUpdates=!1}},N={initialize:T,close:g.flushBatchedUpdates.bind(g)},o=[N,E];i(I.prototype,e.Mixin,{getTransactionWrappers:function(){return o}});var n=new I,C={isBatchingUpdates:!1,batchedUpdates:function(A,M,t,I,g,e){var i=C.isBatchingUpdates;C.isBatchingUpdates=!0,i?A(M,t,I,g,e):n.perform(A,null,M,t,I,g,e)}};A.exports=C},function(A,M,t){"use strict";function I(){if(!L){L=!0,Q.EventEmitter.injectReactEventListener(B),Q.EventPluginHub.injectEventPluginOrder(T),Q.EventPluginHub.injectInstanceHandle(r),Q.EventPluginHub.injectMount(s),Q.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:u,EnterLeaveEventPlugin:E,ChangeEventPlugin:e,SelectEventPlugin:j,BeforeInputEventPlugin:g}),Q.NativeComponent.injectGenericComponentClass(D),Q.NativeComponent.injectTextComponentClass(a),Q.Class.injectMixin(n),Q.DOMProperty.injectDOMPropertyConfig(o),Q.DOMProperty.injectDOMPropertyConfig(w),Q.EmptyComponent.injectEmptyComponent("noscript"),Q.Updates.injectReconcileTransaction(x),Q.Updates.injectBatchingStrategy(c),Q.RootIndex.injectCreateReactRootIndex(N.canUseDOM?i.createReactRootIndex:y.createReactRootIndex),Q.Component.injectEnvironment(C)}}var g=t(430),e=t(432),i=t(433),T=t(435),E=t(436),N=t(10),o=t(439),n=t(441),C=t(109),c=t(212),D=t(445),a=t(211),B=t(453),Q=t(454),r=t(48),s=t(12),x=t(458),j=t(464),y=t(465),u=t(466),w=t(463),L=!1;A.exports={inject:I}},function(A,M,t){"use strict";function I(){if(n.current){var A=n.current.getName();if(A)return" Check the render method of ` + "`" + `"+A+"` + "`" + `."}return""}function g(A,M){if(A._store&&!A._store.validated&&null==A.key){A._store.validated=!0;e("uniqueKey",A,M)}}function e(A,M,t){var g=I();if(!g){var e="string"==typeof t?t:t.displayName||t.name;e&&(g=" Check the top-level render call using <"+e+">.")}var i=D[A]||(D[A]={});if(i[g])return null;i[g]=!0;var T={parentOrOwner:g,url:" See https://fb.me/react-warning-keys for more information.",childOwner:null};return M&&M._owner&&M._owner!==n.current&&(T.childOwner=" It was passed a child from "+M._owner.getName()+"."),T}function i(A,M){if("object"==typeof A)if(Array.isArray(A))for(var t=0;t/,e={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(A){var M=I(A);return A.replace(g," "+e.CHECKSUM_ATTR_NAME+'="'+M+'"$&')},canReuseMarkup:function(A,M){var t=M.getAttribute(e.CHECKSUM_ATTR_NAME);t=t&&parseInt(t,10);var g=I(A);return g===t}};A.exports=e},function(A,M,t){"use strict";var I=t(59),g=I({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOVE_NODE:null,SET_MARKUP:null,TEXT_CONTENT:null});A.exports=g},function(A,M,t){"use strict";function I(A){if("function"==typeof A.type)return A.type;var M=A.type,t=n[M];return null==t&&(n[M]=t=N(M)),t}function g(A){return o?void 0:E(!1),new o(A.type,A.props)}function e(A){return new C(A)}function i(A){return A instanceof C}var T=t(4),E=t(2),N=null,o=null,n={},C=null,c={injectGenericComponentClass:function(A){o=A},injectTextComponentClass:function(A){C=A},injectComponentClasses:function(A){T(n,A)}},D={getComponentClassForElement:I,createInternalComponent:g,createInstanceForText:e,isTextComponent:i,injection:c};A.exports=D},function(A,M,t){"use strict";function I(A,M){}var g=(t(3),{isMounted:function(A){return!1},enqueueCallback:function(A,M){},enqueueForceUpdate:function(A){I(A,"forceUpdate")},enqueueReplaceState:function(A,M){I(A,"replaceState")},enqueueSetState:function(A,M){I(A,"setState")},enqueueSetProps:function(A,M){I(A,"setProps")},enqueueReplaceProps:function(A,M){I(A,"replaceProps")}});A.exports=g},function(A,M,t){"use strict";function I(A){function M(M,t,I,g,e,i){if(g=g||y,i=i||I,null==t[I]){var T=s[e];return M?new Error("Required "+T+" ` + "`" + `"+i+"` + "`" + ` was not specified in "+("` + "`" + `"+g+"` + "`" + `.")):null}return A(t,I,g,e,i)}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}function g(A){function M(M,t,I,g,e){var i=M[t],T=a(i);if(T!==A){var E=s[g],N=B(i);return new Error("Invalid "+E+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+N+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected ")+("` + "`" + `"+A+"` + "`" + `."))}return null}return I(M)}function e(){return I(x.thatReturns(null))}function i(A){function M(M,t,I,g,e){var i=M[t];if(!Array.isArray(i)){var T=s[g],E=a(i);return new Error("Invalid "+T+" ` + "`" + `"+e+"` + "`" + ` of type "+("` + "`" + `"+E+"` + "`" + ` supplied to ` + "`" + `"+I+"` + "`" + `, expected an array."))}for(var N=0;N>"}var r=t(13),s=t(70),x=t(20),j=t(118),y="<>",u={array:g("array"),bool:g("boolean"),func:g("function"),number:g("number"),object:g("object"),string:g("string"),any:e(),arrayOf:i,element:T(),instanceOf:E,node:C(),objectOf:o,oneOf:N,oneOfType:n,shape:c};A.exports=u},function(A,M){"use strict";var t={injectCreateReactRootIndex:function(A){I.createReactRootIndex=A}},I={createReactRootIndex:null,injection:t};A.exports=I},function(A,M){"use strict";var t={currentScrollLeft:0,currentScrollTop:0,refreshScrollValues:function(A){t.currentScrollLeft=A.x,t.currentScrollTop=A.y}};A.exports=t},function(A,M,t){"use strict";function I(A,M){if(null==M?g(!1):void 0,null==A)return M;var t=Array.isArray(A),I=Array.isArray(M);return t&&I?(A.push.apply(A,M),A):t?(A.push(M),A):I?[A].concat(M):[A,M]}var g=t(2);A.exports=I},function(A,M){"use strict";var t=function(A,M,t){Array.isArray(A)?A.forEach(M,t):A&&M.call(t,A)};A.exports=t},function(A,M,t){"use strict";function I(){return!e&&g.canUseDOM&&(e="textContent"in document.documentElement?"textContent":"innerText"),e}var g=t(10),e=null;A.exports=I},function(A,M){"use strict";function t(A){var M=A&&A.nodeName&&A.nodeName.toLowerCase();return M&&("input"===M&&I[A.type]||"textarea"===M)}var I={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};A.exports=t},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(){for(var A=arguments.length,M=Array(A),t=0;t=0&&s.splice(M,1)}function T(A){var M=document.createElement("style");return M.type="text/css",e(A,M),M}function E(A){var M=document.createElement("link");return M.rel="stylesheet",e(A,M),M}function N(A,M){var t,I,g;if(M.singleton){var e=r++;t=Q||(Q=T(M)),I=o.bind(null,t,e,!1),g=o.bind(null,t,e,!0)}else A.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(t=E(M),I=C.bind(null,t),g=function(){i(t),t.href&&URL.revokeObjectURL(t.href)}):(t=T(M),I=n.bind(null,t),g=function(){i(t)});return I(A),function(M){if(M){if(M.css===A.css&&M.media===A.media&&M.sourceMap===A.sourceMap)return;I(A=M)}else g()}}function o(A,M,t,I){var g=t?"":I.css;if(A.styleSheet)A.styleSheet.cssText=x(M,g);else{var e=document.createTextNode(g),i=A.childNodes;i[M]&&A.removeChild(i[M]),i.length?A.insertBefore(e,i[M]):A.appendChild(e)}}function n(A,M){var t=M.css,I=M.media;if(I&&A.setAttribute("media",I),A.styleSheet)A.styleSheet.cssText=t;else{for(;A.firstChild;)A.removeChild(A.firstChild);A.appendChild(document.createTextNode(t))}}function C(A,M){var t=M.css,I=M.sourceMap;I&&(t+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(I))))+" */");var g=new Blob([t],{type:"text/css"}),e=A.href;A.href=URL.createObjectURL(g),e&&URL.revokeObjectURL(e)}var c={},D=function(A){var M;return function(){return"undefined"==typeof M&&(M=A.apply(this,arguments)),M}},a=D(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),B=D(function(){return document.head||document.getElementsByTagName("head")[0]}),Q=null,r=0,s=[];A.exports=function(A,M){M=M||{},"undefined"==typeof M.singleton&&(M.singleton=a()),"undefined"==typeof M.insertAt&&(M.insertAt="bottom");var t=g(A);return I(t,M),function(A){for(var e=[],i=0;i",'"',"` + "`" + `"," ","\r","\n","\t"],D=["{","}","|","\\","^","` + "`" + `"].concat(c),a=["'"].concat(D),B=["%","/","?",";","#"].concat(a),Q=["/","?","#"],r=255,s=/^[+a-z0-9A-Z_-]{0,63}$/,x=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,j={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},u={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=t(360);I.prototype.parse=function(A,M,t){if(!N.isString(A))throw new TypeError("Parameter 'url' must be a string, not "+typeof A);var I=A.indexOf("?"),g=I!==-1&&I127?"x":O[F];if(!m.match(s)){var k=p.slice(0,Y),R=p.slice(Y+1),J=O.match(x);J&&(k.push(J[1]),R.unshift(J[2])),R.length&&(T="/"+R.join(".")+T),this.hostname=k.join(".");break}}}this.hostname.length>r?this.hostname="":this.hostname=this.hostname.toLowerCase(),z||(this.hostname=E.toASCII(this.hostname));var G=this.port?":"+this.port:"",H=this.hostname||"";this.host=H+G,this.href+=this.host,z&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==T[0]&&(T="/"+T))}if(!j[D])for(var Y=0,U=a.length;Y0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return t.search=A.search,t.query=A.query,N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.href=t.format(),t}if(!j.length)return t.pathname=null,t.search?t.path="/"+t.search:t.path=null,t.href=t.format(),t;for(var l=j.slice(-1)[0],Y=(t.host||A.host||j.length>1)&&("."===l||".."===l)||""===l,d=0,h=j.length;h>=0;h--)l=j[h],"."===l?j.splice(h,1):".."===l?(j.splice(h,1),d++):d&&(j.splice(h,1),d--);if(!s&&!x)for(;d--;d)j.unshift("..");!s||""===j[0]||j[0]&&"/"===j[0].charAt(0)||j.unshift(""),Y&&"/"!==j.join("/").substr(-1)&&j.push("");var S=""===j[0]||j[0]&&"/"===j[0].charAt(0);if(w){t.hostname=t.host=S?"":j.length?j.shift():"";var L=!!(t.host&&t.host.indexOf("@")>0)&&t.host.split("@");L&&(t.auth=L.shift(),t.host=t.hostname=L.shift())}return s=s||t.host&&j.length,s&&!S&&j.unshift(""),j.length?t.pathname=j.join("/"):(t.pathname=null,t.path=null),N.isNull(t.pathname)&&N.isNull(t.search)||(t.path=(t.pathname?t.pathname:"")+(t.search?t.search:"")),t.auth=A.auth||t.auth,t.slashes=t.slashes||A.slashes,t.href=t.format(),t},I.prototype.parseHost=function(){var A=this.host,M=n.exec(A);M&&(M=M[0],":"!==M&&(this.port=M.substr(1)),A=A.substr(0,A.length-M.length)),A&&(this.hostname=A)}},function(A,M){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};A.exports=function(A,M){return"number"!=typeof M||t[A]?M:M+"px"}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M,t){return P.LoggedIn()?t():(location.pathname!==z.minioBrowserPrefix&&location.pathname!==z.minioBrowserPrefix+"/"||M(z.minioBrowserPrefix+"/login"),t())}function i(A,M){P.LoggedIn()&&M(""+z.minioBrowserPrefix)}function T(){q<2&&setTimeout(function(){document.querySelector(".page-load").classList.add("pl-"+q),q++,T()},K[q])}t(499);var E=t(1),N=g(E),o=t(16),n=g(o),C=t(485),c=g(C),D=t(125),a=g(D),B=t(230),Q=g(B),r=t(190),s=g(r),x=t(191),j=g(x),y=t(65),u=g(y),w=t(187),L=g(w),l=t(394),Y=g(l),d=t(22),h=g(d),S=t(42),z=(g(S),t(26)),p=t(19),U=I(p),O=t(255),m=g(O),F=t(245),f=g(F),k=t(241),R=g(k),J=t(498),G=(g(J),t(131)),H=g(G),b=t(60),X=g(b);window.Web=H.default;var v=(0,Q.default)(c.default)(a.default)(m.default),W=(0,h.default)(function(A){return A})(R.default),V=(0,h.default)(function(A){return A})(f.default),P=new H.default(window.location.protocol+"//"+window.location.host+z.minioBrowserPrefix+"/webrpc",v.dispatch);window.web=P,v.dispatch(U.setWeb(P));var Z=function(A){return N.default.createElement("div",null,A.children)};n.default.render(N.default.createElement(Y.default,{store:v,web:P},N.default.createElement(j.default,{history:u.default},N.default.createElement(s.default,{path:"/",component:Z},N.default.createElement(s.default,{path:"minio",component:Z},N.default.createElement(L.default,{component:W,onEnter:e}),N.default.createElement(s.default,{path:"login",component:V,onEnter:i}),N.default.createElement(s.default,{path:":bucket",component:W,onEnter:e}),N.default.createElement(s.default,{path:":bucket/*",component:W,onEnter:e}))))),document.getElementById("root"));var K=[0,400],q=0;T(),X.default.getItem("newlyUpdated")&&(v.dispatch(U.showAlert({type:"success",message:"Updated to the latest UI Version."})),X.default.removeItem("newlyUpdated"))},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t-1})))}},{key:"listObjects",value:function(){var A=this.props.dispatch;A(eA.listObjects())}},{key:"selectPrefix",value:function(A,M){A.preventDefault();var t=this.props,I=(t.dispatch,t.currentPath),g=(t.web,t.currentBucket),e=encodeURI(M);if(M.endsWith("/")||""===M){if(M===I)return;D.default.push(TA.pathJoin(g,e))}else window.location=window.location.origin+"/minio/download/"+g+"/"+e+"?token="+DA.default.getItem("token")}},{key:"makeBucket",value:function(A){A.preventDefault();var M=this.refs.makeBucketRef.value;this.refs.makeBucketRef.value="";var t=this.props,I=t.web,g=t.dispatch;this.hideMakeBucketModal(),I.MakeBucket({bucketName:M}).then(function(){g(eA.addBucket(M)),g(eA.selectBucket(M))}).catch(function(A){return g(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideMakeBucketModal",value:function(){var A=this.props.dispatch;A(eA.hideMakeBucketModal())}},{key:"showMakeBucketModal",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showMakeBucketModal())}},{key:"showAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showAbout())}},{key:"hideAbout",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAbout())}},{key:"showBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showBucketPolicy())}},{key:"hideBucketPolicy",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideBucketPolicy())}},{key:"uploadFile",value:function(A){A.preventDefault();var M=this.props,t=M.dispatch,I=M.buckets;if(0===I.length)return void t(eA.showAlert({type:"danger",message:"Bucket needs to be created before trying to upload files."}));var g=A.target.files[0];A.target.value=null,this.xhr=new XMLHttpRequest,t(eA.uploadFile(g,this.xhr))}},{key:"removeObject",value:function(){var A=this,M=this.props,t=M.web,I=M.dispatch,g=(M.currentPath,M.currentBucket),e=M.deleteConfirmation;t.RemoveObject({bucketName:g,objectName:e.object}).then(function(){A.hideDeleteConfirmation(),I(eA.removeObject(e.object))}).catch(function(A){return I(eA.showAlert({type:"danger",message:A.message}))})}},{key:"hideAlert",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.hideAlert())}},{key:"showDeleteConfirmation",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.showDeleteConfirmation(M))}},{key:"hideDeleteConfirmation",value:function(){var A=this.props.dispatch;A(eA.hideDeleteConfirmation())}},{key:"shareObject",value:function(A,M){A.preventDefault();var t=this.props.dispatch;t(eA.shareObject(M))}},{key:"hideShareObjectModal",value:function(){var A=this.props.dispatch;A(eA.hideShareObject())}},{key:"dataType",value:function(A,M){return NA.getDataType(A,M)}},{key:"sortObjectsByName",value:function(A){var M=this.props,t=M.dispatch,I=M.objects,g=M.sortNameOrder;t(eA.setObjects(TA.sortObjectsByName(I,!g))),t(eA.setSortNameOrder(!g))}},{key:"sortObjectsBySize",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortSizeOrder;M(eA.setObjects(TA.sortObjectsBySize(t,!I))),M(eA.setSortSizeOrder(!I))}},{key:"sortObjectsByDate",value:function(){var A=this.props,M=A.dispatch,t=A.objects,I=A.sortDateOrder;M(eA.setObjects(TA.sortObjectsByDate(t,!I))),M(eA.setSortDateOrder(!I))}},{key:"logout",value:function(A){var M=this.props.web;A.preventDefault(),M.Logout(),D.default.push(oA.minioBrowserPrefix+"/login")}},{key:"fullScreen",value:function(A){A.preventDefault();var M=document.documentElement;M.requestFullscreen&&M.requestFullscreen(),M.mozRequestFullScreen&&M.mozRequestFullScreen(),M.webkitRequestFullscreen&&M.webkitRequestFullscreen(),M.msRequestFullscreen&&M.msRequestFullscreen()}},{key:"toggleSidebar",value:function(A){this.props.dispatch(eA.setSidebarStatus(A))}},{key:"hideSidebar",value:function(A){var M=A||window.event,t=M.srcElement||M.target;3===t.nodeType&&(t=t.parentNode);var I=t.id;"feh-trigger"!==I&&this.props.dispatch(eA.setSidebarStatus(!1))}},{key:"showSettings",value:function(A){A.preventDefault();var M=this.props.dispatch;M(eA.showSettings())}},{key:"showMessage",value:function(){var A=this.props.dispatch;A(eA.showAlert({type:"success",message:"Link copied to clipboard!"})),this.hideShareObjectModal()}},{key:"selectTexts",value:function(){this.refs.copyTextInput.select()}},{key:"handleExpireValue",value:function(A,M){M===-1?this.refs[A].stepDown(1):this.refs[A].stepUp(1),7==this.refs.expireDays.value&&(this.refs.expireHours.value=0,this.refs.expireMins.value=0)}},{key:"render",value:function(){var A=this.props.storageInfo,M=A.total,t=A.free,I=this.props,g=I.showMakeBucketModal,e=I.alert,i=I.sortNameOrder,T=I.sortSizeOrder,E=I.sortDateOrder,N=I.showAbout,n=I.showBucketPolicy,c=this.props.serverInfo,D=c.version,a=c.memory,Q=c.platform,r=c.runtime,x=this.props.sidebarStatus,y=this.props.showSettings,w=this.props,l=w.policies,d=w.currentBucket,S=(w.currentPath,this.props.deleteConfirmation),p=this.props.shareObject,U=this.props,O=U.web,F=U.prefixWritable,k=U.istruncated,J=y?o.default.createElement(V.default,null):o.default.createElement("noscript",null),H=o.default.createElement(L.default,{className:(0,C.default)({alert:!0,animated:!0,fadeInDown:e.show,fadeOutUp:!e.show}),bsStyle:e.type,onDismiss:this.hideAlert.bind(this)},o.default.createElement("div",{className:"text-center"},e.message));e.message||(H="");var X=(o.default.createElement(h.default,{id:"tt-sign-out"},"Sign out"),o.default.createElement(h.default,{id:"tt-upload-file"},"Upload file")),W=o.default.createElement(h.default,{id:"tt-create-bucket"},"Create bucket"),P="",K="",_="",AA=M-t,tA=AA/M*100+"%";O.LoggedIn()?K=o.default.createElement($.default,{fullScreenFunc:this.fullScreen.bind(this),aboutFunc:this.showAbout.bind(this),settingsFunc:this.showSettings.bind(this),logoutFunc:this.logout.bind(this)}):P=o.default.createElement("a",{className:"btn btn-danger",href:"/minio/login"},"Login"),O.LoggedIn()&&(_=o.default.createElement("div",{className:"feh-usage"},o.default.createElement("div",{className:"fehu-chart"},o.default.createElement("div",{style:{width:tA}})),o.default.createElement("ul",null,o.default.createElement("li",null,"Used:",B.default.filesize(M-t)),o.default.createElement("li",{className:"pull-right"},"Free:",B.default.filesize(M-AA)))));var gA="";return O.LoggedIn()?gA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," "))),o.default.createElement(Y.default,{placement:"left",overlay:W},o.default.createElement("a",{href:"#",className:"feba-btn feba-bucket",onClick:this.showMakeBucketModal.bind(this)},o.default.createElement("i",{className:"fa fa-hdd-o"}))))):F&&(gA=o.default.createElement(z.default,{dropup:!0,className:"feb-actions",id:"fe-action-toggle"},o.default.createElement(z.default.Toggle,{noCaret:!0,className:"feba-toggle"},o.default.createElement("span",null,o.default.createElement("i",{className:"fa fa-plus"}))),o.default.createElement(z.default.Menu,null,o.default.createElement(Y.default,{placement:"left",overlay:X},o.default.createElement("a",{href:"#",className:"feba-btn feba-upload"},o.default.createElement("input",{type:"file",onChange:this.uploadFile.bind(this),style:{display:"none"},id:"file-input"}),o.default.createElement("label",{htmlFor:"file-input"}," ",o.default.createElement("i",{className:"fa fa-cloud-upload"})," ")))))),o.default.createElement("div",{className:(0,C.default)({"file-explorer":!0,toggled:x})},o.default.createElement(R.default,{searchBuckets:this.searchBuckets.bind(this),selectBucket:this.selectBucket.bind(this),clickOutside:this.hideSidebar.bind(this),showPolicy:this.showBucketPolicy.bind(this)}),o.default.createElement("div",{className:"fe-body"},o.default.createElement(m.default,null,H,o.default.createElement("header",{className:"fe-header-mobile hidden-lg hidden-md"},o.default.createElement("div",{id:"feh-trigger",className:"feh-trigger "+(0,C.default)({"feht-toggled":x}),onClick:this.toggleSidebar.bind(this,!x)},o.default.createElement("div",{className:"feht-lines"},o.default.createElement("div",{className:"top"}),o.default.createElement("div",{className:"center"}),o.default.createElement("div",{className:"bottom"}))),o.default.createElement("img",{className:"mh-logo",src:IA.default,alt:""})),o.default.createElement("header",{className:"fe-header"},o.default.createElement(G.default,{selectPrefix:this.selectPrefix.bind(this)}),_,o.default.createElement("ul",{className:"feh-actions"},o.default.createElement(b.default,null),P,K)),o.default.createElement("div",{className:"feb-container"},o.default.createElement("header",{className:"fesl-row","data-type":"folder"},o.default.createElement("div",{className:"fesl-item fi-name",onClick:this.sortObjectsByName.bind(this),"data-sort":"name"},"Name",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-alpha-desc":i,"fa-sort-alpha-asc":!i})})),o.default.createElement("div",{className:"fesl-item fi-size",onClick:this.sortObjectsBySize.bind(this),"data-sort":"size"},"Size",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-amount-desc":T,"fa-sort-amount-asc":!T})})),o.default.createElement("div",{className:"fesl-item fi-modified",onClick:this.sortObjectsByDate.bind(this),"data-sort":"last-modified"},"Last Modified",o.default.createElement("i",{className:(0,C.default)({"fesli-sort":!0,fa:!0,"fa-sort-numeric-desc":E,"fa-sort-numeric-asc":!E})})),o.default.createElement("div",{className:"fesl-item fi-actions"}))),o.default.createElement("div",{className:"feb-container"},o.default.createElement(BA.default,{loadMore:this.listObjects.bind(this),hasMore:k,useWindow:!0,initialLoad:!1},o.default.createElement(f.default,{dataType:this.dataType.bind(this),selectPrefix:this.selectPrefix.bind(this),showDeleteConfirmation:this.showDeleteConfirmation.bind(this),shareObject:this.shareObject.bind(this)})),o.default.createElement("div",{className:"text-center",style:{display:k?"block":"none"}},o.default.createElement("span",null,"Loading..."))),o.default.createElement(v.default,null),gA,o.default.createElement(s.default,{className:"modal-create-bucket",bsSize:"small",animation:!1,show:g,onHide:this.hideMakeBucketModal.bind(this)},o.default.createElement("button",{className:"close close-alt",onClick:this.hideMakeBucketModal.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement(j.default,null,o.default.createElement("form",{onSubmit:this.makeBucket.bind(this)},o.default.createElement("div",{className:"input-group"},o.default.createElement("input",{className:"ig-text",type:"text",ref:"makeBucketRef",placeholder:"Bucket Name",autoFocus:!0}),o.default.createElement("i",{className:"ig-helpers"}))))),o.default.createElement(s.default,{className:"modal-about modal-dark",animation:!1,show:N,onHide:this.hideAbout.bind(this)},o.default.createElement("button",{className:"close",onClick:this.hideAbout.bind(this)},o.default.createElement("span",null,"×")),o.default.createElement("div",{className:"ma-inner"},o.default.createElement("div",{className:"mai-item hidden-xs"},o.default.createElement("a",{href:"https://minio.io",target:"_blank"},o.default.createElement("img",{className:"maii-logo",src:IA.default,alt:""}))),o.default.createElement("div",{className:"mai-item"},o.default.createElement("ul",{className:"maii-list"},o.default.createElement("li",null,o.default.createElement("div",null,"Version"),o.default.createElement("small",null,D)),o.default.createElement("li",null,o.default.createElement("div",null,"Memory"),o.default.createElement("small",null,a)),o.default.createElement("li",null,o.default.createElement("div",null,"Platform"),o.default.createElement("small",null,Q)),o.default.createElement("li",null,o.default.createElement("div",null,"Runtime"),o.default.createElement("small",null,r)))))),o.default.createElement(s.default,{className:"modal-policy",animation:!1,show:n,onHide:this.hideBucketPolicy.bind(this)},o.default.createElement(u.default,null,"Bucket Policy (",d,")",o.default.createElement("button",{className:"close close-alt",onClick:this.hideBucketPolicy.bind(this)},o.default.createElement("span",null,"×"))),o.default.createElement("div",{className:"pm-body"},o.default.createElement(Z.default,{bucket:d}),l.map(function(A,M){return o.default.createElement(q.default,{key:M,prefix:A.prefix,policy:A.policy})}))),o.default.createElement(MA.default,{show:S.show,icon:"fa fa-exclamation-triangle mci-red",text:"Are you sure you want to delete?",sub:"This cannot be undone!",okText:"Delete",cancelText:"Cancel",okHandler:this.removeObject.bind(this),cancelHandler:this.hideDeleteConfirmation.bind(this)}),o.default.createElement(s.default,{show:p.show,animation:!1,onHide:this.hideShareObjectModal.bind(this),bsSize:"small"},o.default.createElement(u.default,null,"Share Object"),o.default.createElement(j.default,null,o.default.createElement("div",{className:"input-group copy-text"},o.default.createElement("label",null,"Shareable Link"),o.default.createElement("input",{type:"text",ref:"copyTextInput",readOnly:"readOnly",value:window.location.protocol+"//"+p.url,onClick:this.selectTexts.bind(this)})),o.default.createElement("div",{className:"input-group",style:{display:O.LoggedIn()?"block":"none"}},o.default.createElement("label",null,"Expires in"),o.default.createElement("div",{className:"set-expire"},o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireDays",1)}),o.default.createElement("div",{className:"set-expire-title"},"Days"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireDays",type:"number",min:0,max:7,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireDays",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireHours",1)}),o.default.createElement("div",{className:"set-expire-title"},"Hours"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireHours",type:"number",min:0,max:24,defaultValue:0})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireHours",-1)})),o.default.createElement("div",{className:"set-expire-item"},o.default.createElement("i",{className:"set-expire-increase",onClick:this.handleExpireValue.bind(this,"expireMins",1)}),o.default.createElement("div",{className:"set-expire-title"},"Minutes"),o.default.createElement("div",{className:"set-expire-value"},o.default.createElement("input",{ref:"expireMins",type:"number",min:1,max:60,defaultValue:45})),o.default.createElement("i",{className:"set-expire-decrease",onClick:this.handleExpireValue.bind(this,"expireMins",-1)}))))),o.default.createElement("div",{className:"modal-footer"},o.default.createElement(CA.default,{text:p.url,onCopy:this.showMessage.bind(this)},o.default.createElement("button",{className:"btn btn-success"},"Copy Link")),o.default.createElement("button",{className:"btn btn-link",onClick:this.hideShareObjectModal.bind(this)},"Cancel"))),J)))}}]),M}(o.default.Component);M.default=QA},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(91),N=I(E),o=function(A){var M=A.fullScreenFunc,t=A.aboutFunc,I=A.settingsFunc,g=A.logoutFunc;return e.default.createElement("li",null,e.default.createElement(N.default,{pullRight:!0,id:"top-right-menu"},e.default.createElement(N.default.Toggle,{noCaret:!0},e.default.createElement("i",{className:"fa fa-reorder"})),e.default.createElement(N.default.Menu,{className:"dropdown-menu-right"},e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://github.com/minio/miniobrowser"},"Github ",e.default.createElement("i",{className:"fa fa-github"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:M},"Fullscreen ",e.default.createElement("i",{className:"fa fa-expand"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://docs.minio.io/"},"Documentation ",e.default.createElement("i",{className:"fa fa-book"}))),e.default.createElement("li",null,e.default.createElement("a",{target:"_blank",href:"https://slack.minio.io"},"Ask for help ",e.default.createElement("i",{className:"fa fa-question-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:t},"About ",e.default.createElement("i",{className:"fa fa-info-circle"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:I},"Settings ",e.default.createElement("i",{className:"fa fa-cog"}))),e.default.createElement("li",null,e.default.createElement("a",{href:"",onClick:g},"Sign Out ",e.default.createElement("i",{className:"fa fa-sign-out"}))))))};M.default=(0,T.default)(function(A){return A})(o)},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=t(22),T=I(i),E=t(95),N=I(E),o=t(94),n=I(o),C=function(A){var M=A.latestUiVersion;return M===currentUiVersion?e.default.createElement("noscript",null):e.default.createElement("li",{className:"hidden-xs hidden-sm"},e.default.createElement("a",{href:""},e.default.createElement(n.default,{placement:"left",overlay:e.default.createElement(N.default,{id:"tt-version-update"},"New update available. Click to refresh.")}," ",e.default.createElement("i",{className:"fa fa-refresh"})," ")))};M.default=(0,T.default)(function(A){return{latestUiVersion:A.latestUiVersion}})(C)},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){ +return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{buckets:[],visibleBuckets:[],objects:[],istruncated:!0,storageInfo:{},serverInfo:{},currentBucket:"",currentPath:"",showMakeBucketModal:!1,uploads:{},alert:{show:!1,type:"danger",message:""},loginError:!1,sortNameOrder:!1,sortSizeOrder:!1,sortDateOrder:!1,latestUiVersion:currentUiVersion,sideBarActive:!1,loginRedirectPath:E.minioBrowserPrefix,settings:{accessKey:"",secretKey:"",secretKeyVisible:!1},showSettings:!1,policies:[],deleteConfirmation:{object:"",show:!1},shareObject:{show:!1,url:"",expiry:604800},prefixWritable:!1},M=arguments[1],t=Object.assign({},A);switch(M.type){case T.SET_WEB:t.web=M.web;break;case T.SET_BUCKETS:t.buckets=M.buckets;break;case T.ADD_BUCKET:t.buckets=[M.bucket].concat(e(t.buckets)),t.visibleBuckets=[M.bucket].concat(e(t.visibleBuckets));break;case T.SET_VISIBLE_BUCKETS:t.visibleBuckets=M.visibleBuckets;break;case T.SET_CURRENT_BUCKET:t.currentBucket=M.currentBucket;break;case T.SET_OBJECTS:M.objects.length?(t.objects=[].concat(e(t.objects),e(M.objects)),t.marker=M.marker,t.istruncated=M.istruncated):(t.objects=[],t.marker="",t.istruncated=M.istruncated);break;case T.SET_CURRENT_PATH:t.currentPath=M.currentPath;break;case T.SET_STORAGE_INFO:t.storageInfo=M.storageInfo;break;case T.SET_SERVER_INFO:t.serverInfo=M.serverInfo;break;case T.SHOW_MAKEBUCKET_MODAL:t.showMakeBucketModal=M.showMakeBucketModal;break;case T.UPLOAD_PROGRESS:t.uploads=Object.assign({},t.uploads),t.uploads[M.slug].loaded=M.loaded;break;case T.ADD_UPLOAD:t.uploads=Object.assign({},t.uploads,g({},M.slug,{loaded:0,size:M.size,xhr:M.xhr,name:M.name}));break;case T.STOP_UPLOAD:t.uploads=Object.assign({},t.uploads),delete t.uploads[M.slug];break;case T.SET_ALERT:t.alert.alertTimeout&&clearTimeout(t.alert.alertTimeout),M.alert.show?t.alert=M.alert:t.alert=Object.assign({},t.alert,{show:!1});break;case T.SET_LOGIN_ERROR:t.loginError=!0;break;case T.SET_SHOW_ABORT_MODAL:t.showAbortModal=M.showAbortModal;break;case T.SHOW_ABOUT:t.showAbout=M.showAbout;break;case T.SET_SORT_NAME_ORDER:t.sortNameOrder=M.sortNameOrder;break;case T.SET_SORT_SIZE_ORDER:t.sortSizeOrder=M.sortSizeOrder;break;case T.SET_SORT_DATE_ORDER:t.sortDateOrder=M.sortDateOrder;break;case T.SET_LATEST_UI_VERSION:t.latestUiVersion=M.latestUiVersion;break;case T.SET_SIDEBAR_STATUS:t.sidebarStatus=M.sidebarStatus;break;case T.SET_LOGIN_REDIRECT_PATH:t.loginRedirectPath=M.path;case T.SET_LOAD_BUCKET:t.loadBucket=M.loadBucket;break;case T.SET_LOAD_PATH:t.loadPath=M.loadPath;break;case T.SHOW_SETTINGS:t.showSettings=M.showSettings;break;case T.SET_SETTINGS:t.settings=Object.assign({},t.settings,M.settings);break;case T.SHOW_BUCKET_POLICY:t.showBucketPolicy=M.showBucketPolicy;break;case T.SET_POLICIES:t.policies=M.policies;break;case T.DELETE_CONFIRMATION:t.deleteConfirmation=Object.assign({},M.payload);break;case T.SET_SHARE_OBJECT:t.shareObject=Object.assign({},M.shareObject);break;case T.SET_PREFIX_WRITABLE:t.prefixWritable=M.prefixWritable;break;case T.REMOVE_OBJECT:var I=t.objects.findIndex(function(A){return A.name===M.object});if(I==-1)break;t.objects=[].concat(e(t.objects.slice(0,I)),e(t.objects.slice(I+1)))}return t}},function(A,M,t){A.exports={default:t(260),__esModule:!0}},function(A,M,t){t(270),A.exports=t(49).Object.assign},function(A,M,t){var I=t(80);A.exports=function(A,M){return I.create(A,M)}},function(A,M,t){t(271),A.exports=t(49).Object.keys},function(A,M,t){t(272),A.exports=t(49).Object.setPrototypeOf},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M,t){var I=t(136);A.exports=function(A){if(!I(A))throw TypeError(A+" is not an object!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(263);A.exports=Object("z").propertyIsEnumerable(0)?Object:function(A){return"String"==I(A)?A.split(""):Object(A)}},function(A,M,t){var I=t(80),g=t(137),e=t(266);A.exports=t(135)(function(){var A=Object.assign,M={},t={},I=Symbol(),g="abcdefghijklmnopqrst";return M[I]=7,g.split("").forEach(function(A){t[A]=A}),7!=A({},M)[I]||Object.keys(A({},t)).join("")!=g})?function(A,M){for(var t=g(A),i=arguments,T=i.length,E=1,N=I.getKeys,o=I.getSymbols,n=I.isEnum;T>E;)for(var C,c=e(i[E++]),D=o?N(c).concat(o(c)):N(c),a=D.length,B=0;a>B;)n.call(c,C=D[B++])&&(t[C]=c[C]);return t}:Object.assign},function(A,M,t){var I=t(79),g=t(49),e=t(135);A.exports=function(A,M){var t=(g.Object||{})[A]||Object[A],i={};i[A]=M(t),I(I.S+I.F*e(function(){t(1)}),"Object",i)}},function(A,M,t){var I=t(80).getDesc,g=t(136),e=t(262),i=function(A,M){if(e(A),!g(M)&&null!==M)throw TypeError(M+": can't set as prototype!")};A.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(A,M,g){try{g=t(134)(Function.call,I(Object.prototype,"__proto__").set,2), +g(A,[]),M=!(A instanceof Array)}catch(A){M=!0}return function(A,t){return i(A,t),M?A.__proto__=t:g(A,t),A}}({},!1):void 0),check:i}},function(A,M,t){var I=t(79);I(I.S+I.F,"Object",{assign:t(267)})},function(A,M,t){var I=t(137);t(268)("keys",function(A){return function(M){return A(I(M))}})},function(A,M,t){var I=t(79);I(I.S,"Object",{setPrototypeOf:t(269).set})},function(A,M,t){function I(A){if(A)return g(A)}function g(A){for(var M in I.prototype)A[M]=I.prototype[M];return A}A.exports=I,I.prototype.on=I.prototype.addEventListener=function(A,M){return this._callbacks=this._callbacks||{},(this._callbacks["$"+A]=this._callbacks["$"+A]||[]).push(M),this},I.prototype.once=function(A,M){function t(){this.off(A,t),M.apply(this,arguments)}return t.fn=M,this.on(A,t),this},I.prototype.off=I.prototype.removeListener=I.prototype.removeAllListeners=I.prototype.removeEventListener=function(A,M){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+A];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+A],this;for(var I,g=0;gli{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\\F000"}.fa-music:before{content:"\\F001"}.fa-search:before{content:"\\F002"}.fa-envelope-o:before{content:"\\F003"}.fa-heart:before{content:"\\F004"}.fa-star:before{content:"\\F005"}.fa-star-o:before{content:"\\F006"}.fa-user:before{content:"\\F007"}.fa-film:before{content:"\\F008"}.fa-th-large:before{content:"\\F009"}.fa-th:before{content:"\\F00A"}.fa-th-list:before{content:"\\F00B"}.fa-check:before{content:"\\F00C"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\\F00D"}.fa-search-plus:before{content:"\\F00E"}.fa-search-minus:before{content:"\\F010"}.fa-power-off:before{content:"\\F011"}.fa-signal:before{content:"\\F012"}.fa-cog:before,.fa-gear:before{content:"\\F013"}.fa-trash-o:before{content:"\\F014"}.fa-home:before{content:"\\F015"}.fa-file-o:before{content:"\\F016"}.fa-clock-o:before{content:"\\F017"}.fa-road:before{content:"\\F018"}.fa-download:before{content:"\\F019"}.fa-arrow-circle-o-down:before{content:"\\F01A"}.fa-arrow-circle-o-up:before{content:"\\F01B"}.fa-inbox:before{content:"\\F01C"}.fa-play-circle-o:before{content:"\\F01D"}.fa-repeat:before,.fa-rotate-right:before{content:"\\F01E"}.fa-refresh:before{content:"\\F021"}.fa-list-alt:before{content:"\\F022"}.fa-lock:before{content:"\\F023"}.fa-flag:before{content:"\\F024"}.fa-headphones:before{content:"\\F025"}.fa-volume-off:before{content:"\\F026"}.fa-volume-down:before{content:"\\F027"}.fa-volume-up:before{content:"\\F028"}.fa-qrcode:before{content:"\\F029"}.fa-barcode:before{content:"\\F02A"}.fa-tag:before{content:"\\F02B"}.fa-tags:before{content:"\\F02C"}.fa-book:before{content:"\\F02D"}.fa-bookmark:before{content:"\\F02E"}.fa-print:before{content:"\\F02F"}.fa-camera:before{content:"\\F030"}.fa-font:before{content:"\\F031"}.fa-bold:before{content:"\\F032"}.fa-italic:before{content:"\\F033"}.fa-text-height:before{content:"\\F034"}.fa-text-width:before{content:"\\F035"}.fa-align-left:before{content:"\\F036"}.fa-align-center:before{content:"\\F037"}.fa-align-right:before{content:"\\F038"}.fa-align-justify:before{content:"\\F039"}.fa-list:before{content:"\\F03A"}.fa-dedent:before,.fa-outdent:before{content:"\\F03B"}.fa-indent:before{content:"\\F03C"}.fa-video-camera:before{content:"\\F03D"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\\F03E"}.fa-pencil:before{content:"\\F040"}.fa-map-marker:before{content:"\\F041"}.fa-adjust:before{content:"\\F042"}.fa-tint:before{content:"\\F043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\\F044"}.fa-share-square-o:before{content:"\\F045"}.fa-check-square-o:before{content:"\\F046"}.fa-arrows:before{content:"\\F047"}.fa-step-backward:before{content:"\\F048"}.fa-fast-backward:before{content:"\\F049"}.fa-backward:before{content:"\\F04A"}.fa-play:before{content:"\\F04B"}.fa-pause:before{content:"\\F04C"}.fa-stop:before{content:"\\F04D"}.fa-forward:before{content:"\\F04E"}.fa-fast-forward:before{content:"\\F050"}.fa-step-forward:before{content:"\\F051"}.fa-eject:before{content:"\\F052"}.fa-chevron-left:before{content:"\\F053"}.fa-chevron-right:before{content:"\\F054"}.fa-plus-circle:before{content:"\\F055"}.fa-minus-circle:before{content:"\\F056"}.fa-times-circle:before{content:"\\F057"}.fa-check-circle:before{content:"\\F058"}.fa-question-circle:before{content:"\\F059"}.fa-info-circle:before{content:"\\F05A"}.fa-crosshairs:before{content:"\\F05B"}.fa-times-circle-o:before{content:"\\F05C"}.fa-check-circle-o:before{content:"\\F05D"}.fa-ban:before{content:"\\F05E"}.fa-arrow-left:before{content:"\\F060"}.fa-arrow-right:before{content:"\\F061"}.fa-arrow-up:before{content:"\\F062"}.fa-arrow-down:before{content:"\\F063"}.fa-mail-forward:before,.fa-share:before{content:"\\F064"}.fa-expand:before{content:"\\F065"}.fa-compress:before{content:"\\F066"}.fa-plus:before{content:"\\F067"}.fa-minus:before{content:"\\F068"}.fa-asterisk:before{content:"\\F069"}.fa-exclamation-circle:before{content:"\\F06A"}.fa-gift:before{content:"\\F06B"}.fa-leaf:before{content:"\\F06C"}.fa-fire:before{content:"\\F06D"}.fa-eye:before{content:"\\F06E"}.fa-eye-slash:before{content:"\\F070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\\F071"}.fa-plane:before{content:"\\F072"}.fa-calendar:before{content:"\\F073"}.fa-random:before{content:"\\F074"}.fa-comment:before{content:"\\F075"}.fa-magnet:before{content:"\\F076"}.fa-chevron-up:before{content:"\\F077"}.fa-chevron-down:before{content:"\\F078"}.fa-retweet:before{content:"\\F079"}.fa-shopping-cart:before{content:"\\F07A"}.fa-folder:before{content:"\\F07B"}.fa-folder-open:before{content:"\\F07C"}.fa-arrows-v:before{content:"\\F07D"}.fa-arrows-h:before{content:"\\F07E"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\\F080"}.fa-twitter-square:before{content:"\\F081"}.fa-facebook-square:before{content:"\\F082"}.fa-camera-retro:before{content:"\\F083"}.fa-key:before{content:"\\F084"}.fa-cogs:before,.fa-gears:before{content:"\\F085"}.fa-comments:before{content:"\\F086"}.fa-thumbs-o-up:before{content:"\\F087"}.fa-thumbs-o-down:before{content:"\\F088"}.fa-star-half:before{content:"\\F089"}.fa-heart-o:before{content:"\\F08A"}.fa-sign-out:before{content:"\\F08B"}.fa-linkedin-square:before{content:"\\F08C"}.fa-thumb-tack:before{content:"\\F08D"}.fa-external-link:before{content:"\\F08E"}.fa-sign-in:before{content:"\\F090"}.fa-trophy:before{content:"\\F091"}.fa-github-square:before{content:"\\F092"}.fa-upload:before{content:"\\F093"}.fa-lemon-o:before{content:"\\F094"}.fa-phone:before{content:"\\F095"}.fa-square-o:before{content:"\\F096"}.fa-bookmark-o:before{content:"\\F097"}.fa-phone-square:before{content:"\\F098"}.fa-twitter:before{content:"\\F099"}.fa-facebook-f:before,.fa-facebook:before{content:"\\F09A"}.fa-github:before{content:"\\F09B"}.fa-unlock:before{content:"\\F09C"}.fa-credit-card:before{content:"\\F09D"}.fa-feed:before,.fa-rss:before{content:"\\F09E"}.fa-hdd-o:before{content:"\\F0A0"}.fa-bullhorn:before{content:"\\F0A1"}.fa-bell:before{content:"\\F0F3"}.fa-certificate:before{content:"\\F0A3"}.fa-hand-o-right:before{content:"\\F0A4"}.fa-hand-o-left:before{content:"\\F0A5"}.fa-hand-o-up:before{content:"\\F0A6"}.fa-hand-o-down:before{content:"\\F0A7"}.fa-arrow-circle-left:before{content:"\\F0A8"}.fa-arrow-circle-right:before{content:"\\F0A9"}.fa-arrow-circle-up:before{content:"\\F0AA"}.fa-arrow-circle-down:before{content:"\\F0AB"}.fa-globe:before{content:"\\F0AC"}.fa-wrench:before{content:"\\F0AD"}.fa-tasks:before{content:"\\F0AE"}.fa-filter:before{content:"\\F0B0"}.fa-briefcase:before{content:"\\F0B1"}.fa-arrows-alt:before{content:"\\F0B2"}.fa-group:before,.fa-users:before{content:"\\F0C0"}.fa-chain:before,.fa-link:before{content:"\\F0C1"}.fa-cloud:before{content:"\\F0C2"}.fa-flask:before{content:"\\F0C3"}.fa-cut:before,.fa-scissors:before{content:"\\F0C4"}.fa-copy:before,.fa-files-o:before{content:"\\F0C5"}.fa-paperclip:before{content:"\\F0C6"}.fa-floppy-o:before,.fa-save:before{content:"\\F0C7"}.fa-square:before{content:"\\F0C8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\\F0C9"}.fa-list-ul:before{content:"\\F0CA"}.fa-list-ol:before{content:"\\F0CB"}.fa-strikethrough:before{content:"\\F0CC"}.fa-underline:before{content:"\\F0CD"}.fa-table:before{content:"\\F0CE"}.fa-magic:before{content:"\\F0D0"}.fa-truck:before{content:"\\F0D1"}.fa-pinterest:before{content:"\\F0D2"}.fa-pinterest-square:before{content:"\\F0D3"}.fa-google-plus-square:before{content:"\\F0D4"}.fa-google-plus:before{content:"\\F0D5"}.fa-money:before{content:"\\F0D6"}.fa-caret-down:before{content:"\\F0D7"}.fa-caret-up:before{content:"\\F0D8"}.fa-caret-left:before{content:"\\F0D9"}.fa-caret-right:before{content:"\\F0DA"}.fa-columns:before{content:"\\F0DB"}.fa-sort:before,.fa-unsorted:before{content:"\\F0DC"}.fa-sort-desc:before,.fa-sort-down:before{content:"\\F0DD"}.fa-sort-asc:before,.fa-sort-up:before{content:"\\F0DE"}.fa-envelope:before{content:"\\F0E0"}.fa-linkedin:before{content:"\\F0E1"}.fa-rotate-left:before,.fa-undo:before{content:"\\F0E2"}.fa-gavel:before,.fa-legal:before{content:"\\F0E3"}.fa-dashboard:before,.fa-tachometer:before{content:"\\F0E4"}.fa-comment-o:before{content:"\\F0E5"}.fa-comments-o:before{content:"\\F0E6"}.fa-bolt:before,.fa-flash:before{content:"\\F0E7"}.fa-sitemap:before{content:"\\F0E8"}.fa-umbrella:before{content:"\\F0E9"}.fa-clipboard:before,.fa-paste:before{content:"\\F0EA"}.fa-lightbulb-o:before{content:"\\F0EB"}.fa-exchange:before{content:"\\F0EC"}.fa-cloud-download:before{content:"\\F0ED"}.fa-cloud-upload:before{content:"\\F0EE"}.fa-user-md:before{content:"\\F0F0"}.fa-stethoscope:before{content:"\\F0F1"}.fa-suitcase:before{content:"\\F0F2"}.fa-bell-o:before{content:"\\F0A2"}.fa-coffee:before{content:"\\F0F4"}.fa-cutlery:before{content:"\\F0F5"}.fa-file-text-o:before{content:"\\F0F6"}.fa-building-o:before{content:"\\F0F7"}.fa-hospital-o:before{content:"\\F0F8"}.fa-ambulance:before{content:"\\F0F9"}.fa-medkit:before{content:"\\F0FA"}.fa-fighter-jet:before{content:"\\F0FB"}.fa-beer:before{content:"\\F0FC"}.fa-h-square:before{content:"\\F0FD"}.fa-plus-square:before{content:"\\F0FE"}.fa-angle-double-left:before{content:"\\F100"}.fa-angle-double-right:before{content:"\\F101"}.fa-angle-double-up:before{content:"\\F102"}.fa-angle-double-down:before{content:"\\F103"}.fa-angle-left:before{content:"\\F104"}.fa-angle-right:before{content:"\\F105"}.fa-angle-up:before{content:"\\F106"}.fa-angle-down:before{content:"\\F107"}.fa-desktop:before{content:"\\F108"}.fa-laptop:before{content:"\\F109"}.fa-tablet:before{content:"\\F10A"}.fa-mobile-phone:before,.fa-mobile:before{content:"\\F10B"}.fa-circle-o:before{content:"\\F10C"}.fa-quote-left:before{content:"\\F10D"}.fa-quote-right:before{content:"\\F10E"}.fa-spinner:before{content:"\\F110"}.fa-circle:before{content:"\\F111"}.fa-mail-reply:before,.fa-reply:before{content:"\\F112"}.fa-github-alt:before{content:"\\F113"}.fa-folder-o:before{content:"\\F114"}.fa-folder-open-o:before{content:"\\F115"}.fa-smile-o:before{content:"\\F118"}.fa-frown-o:before{content:"\\F119"}.fa-meh-o:before{content:"\\F11A"}.fa-gamepad:before{content:"\\F11B"}.fa-keyboard-o:before{content:"\\F11C"}.fa-flag-o:before{content:"\\F11D"}.fa-flag-checkered:before{content:"\\F11E"}.fa-terminal:before{content:"\\F120"}.fa-code:before{content:"\\F121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\\F122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\\F123"}.fa-location-arrow:before{content:"\\F124"}.fa-crop:before{content:"\\F125"}.fa-code-fork:before{content:"\\F126"}.fa-chain-broken:before,.fa-unlink:before{content:"\\F127"}.fa-question:before{content:"\\F128"}.fa-info:before{content:"\\F129"}.fa-exclamation:before{content:"\\F12A"}.fa-superscript:before{content:"\\F12B"}.fa-subscript:before{content:"\\F12C"}.fa-eraser:before{content:"\\F12D"}.fa-puzzle-piece:before{content:"\\F12E"}.fa-microphone:before{content:"\\F130"}.fa-microphone-slash:before{content:"\\F131"}.fa-shield:before{content:"\\F132"}.fa-calendar-o:before{content:"\\F133"}.fa-fire-extinguisher:before{content:"\\F134"}.fa-rocket:before{content:"\\F135"}.fa-maxcdn:before{content:"\\F136"}.fa-chevron-circle-left:before{content:"\\F137"}.fa-chevron-circle-right:before{content:"\\F138"}.fa-chevron-circle-up:before{content:"\\F139"}.fa-chevron-circle-down:before{content:"\\F13A"}.fa-html5:before{content:"\\F13B"}.fa-css3:before{content:"\\F13C"}.fa-anchor:before{content:"\\F13D"}.fa-unlock-alt:before{content:"\\F13E"}.fa-bullseye:before{content:"\\F140"}.fa-ellipsis-h:before{content:"\\F141"}.fa-ellipsis-v:before{content:"\\F142"}.fa-rss-square:before{content:"\\F143"}.fa-play-circle:before{content:"\\F144"}.fa-ticket:before{content:"\\F145"}.fa-minus-square:before{content:"\\F146"}.fa-minus-square-o:before{content:"\\F147"}.fa-level-up:before{content:"\\F148"}.fa-level-down:before{content:"\\F149"}.fa-check-square:before{content:"\\F14A"}.fa-pencil-square:before{content:"\\F14B"}.fa-external-link-square:before{content:"\\F14C"}.fa-share-square:before{content:"\\F14D"}.fa-compass:before{content:"\\F14E"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\\F150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\\F151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\\F152"}.fa-eur:before,.fa-euro:before{content:"\\F153"}.fa-gbp:before{content:"\\F154"}.fa-dollar:before,.fa-usd:before{content:"\\F155"}.fa-inr:before,.fa-rupee:before{content:"\\F156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\\F157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\\F158"}.fa-krw:before,.fa-won:before{content:"\\F159"}.fa-bitcoin:before,.fa-btc:before{content:"\\F15A"}.fa-file:before{content:"\\F15B"}.fa-file-text:before{content:"\\F15C"}.fa-sort-alpha-asc:before{content:"\\F15D"}.fa-sort-alpha-desc:before{content:"\\F15E"}.fa-sort-amount-asc:before{content:"\\F160"}.fa-sort-amount-desc:before{content:"\\F161"}.fa-sort-numeric-asc:before{content:"\\F162"}.fa-sort-numeric-desc:before{content:"\\F163"}.fa-thumbs-up:before{content:"\\F164"}.fa-thumbs-down:before{content:"\\F165"}.fa-youtube-square:before{content:"\\F166"}.fa-youtube:before{content:"\\F167"}.fa-xing:before{content:"\\F168"}.fa-xing-square:before{content:"\\F169"}.fa-youtube-play:before{content:"\\F16A"}.fa-dropbox:before{content:"\\F16B"}.fa-stack-overflow:before{content:"\\F16C"}.fa-instagram:before{content:"\\F16D"}.fa-flickr:before{content:"\\F16E"}.fa-adn:before{content:"\\F170"}.fa-bitbucket:before{content:"\\F171"}.fa-bitbucket-square:before{content:"\\F172"}.fa-tumblr:before{content:"\\F173"}.fa-tumblr-square:before{content:"\\F174"}.fa-long-arrow-down:before{content:"\\F175"}.fa-long-arrow-up:before{content:"\\F176"}.fa-long-arrow-left:before{content:"\\F177"}.fa-long-arrow-right:before{content:"\\F178"}.fa-apple:before{content:"\\F179"}.fa-windows:before{content:"\\F17A"}.fa-android:before{content:"\\F17B"}.fa-linux:before{content:"\\F17C"}.fa-dribbble:before{content:"\\F17D"}.fa-skype:before{content:"\\F17E"}.fa-foursquare:before{content:"\\F180"}.fa-trello:before{content:"\\F181"}.fa-female:before{content:"\\F182"}.fa-male:before{content:"\\F183"}.fa-gittip:before,.fa-gratipay:before{content:"\\F184"}.fa-sun-o:before{content:"\\F185"}.fa-moon-o:before{content:"\\F186"}.fa-archive:before{content:"\\F187"}.fa-bug:before{content:"\\F188"}.fa-vk:before{content:"\\F189"}.fa-weibo:before{content:"\\F18A"}.fa-renren:before{content:"\\F18B"}.fa-pagelines:before{content:"\\F18C"}.fa-stack-exchange:before{content:"\\F18D"}.fa-arrow-circle-o-right:before{content:"\\F18E"}.fa-arrow-circle-o-left:before{content:"\\F190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\\F191"}.fa-dot-circle-o:before{content:"\\F192"}.fa-wheelchair:before{content:"\\F193"}.fa-vimeo-square:before{content:"\\F194"}.fa-try:before,.fa-turkish-lira:before{content:"\\F195"}.fa-plus-square-o:before{content:"\\F196"}.fa-space-shuttle:before{content:"\\F197"}.fa-slack:before{content:"\\F198"}.fa-envelope-square:before{content:"\\F199"}.fa-wordpress:before{content:"\\F19A"}.fa-openid:before{content:"\\F19B"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\\F19C"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\\F19D"}.fa-yahoo:before{content:"\\F19E"}.fa-google:before{content:"\\F1A0"}.fa-reddit:before{content:"\\F1A1"}.fa-reddit-square:before{content:"\\F1A2"}.fa-stumbleupon-circle:before{content:"\\F1A3"}.fa-stumbleupon:before{content:"\\F1A4"}.fa-delicious:before{content:"\\F1A5"}.fa-digg:before{content:"\\F1A6"}.fa-pied-piper-pp:before{content:"\\F1A7"}.fa-pied-piper-alt:before{content:"\\F1A8"}.fa-drupal:before{content:"\\F1A9"}.fa-joomla:before{content:"\\F1AA"}.fa-language:before{content:"\\F1AB"}.fa-fax:before{content:"\\F1AC"}.fa-building:before{content:"\\F1AD"}.fa-child:before{content:"\\F1AE"}.fa-paw:before{content:"\\F1B0"}.fa-spoon:before{content:"\\F1B1"}.fa-cube:before{content:"\\F1B2"}.fa-cubes:before{content:"\\F1B3"}.fa-behance:before{content:"\\F1B4"}.fa-behance-square:before{content:"\\F1B5"}.fa-steam:before{content:"\\F1B6"}.fa-steam-square:before{content:"\\F1B7"}.fa-recycle:before{content:"\\F1B8"}.fa-automobile:before,.fa-car:before{content:"\\F1B9"}.fa-cab:before,.fa-taxi:before{content:"\\F1BA"}.fa-tree:before{content:"\\F1BB"}.fa-spotify:before{content:"\\F1BC"}.fa-deviantart:before{content:"\\F1BD"}.fa-soundcloud:before{content:"\\F1BE"}.fa-database:before{content:"\\F1C0"}.fa-file-pdf-o:before{content:"\\F1C1"}.fa-file-word-o:before{content:"\\F1C2"}.fa-file-excel-o:before{content:"\\F1C3"}.fa-file-powerpoint-o:before{content:"\\F1C4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\\F1C5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\\F1C6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\\F1C7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\\F1C8"}.fa-file-code-o:before{content:"\\F1C9"}.fa-vine:before{content:"\\F1CA"}.fa-codepen:before{content:"\\F1CB"}.fa-jsfiddle:before{content:"\\F1CC"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\\F1CD"}.fa-circle-o-notch:before{content:"\\F1CE"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\\F1D0"}.fa-empire:before,.fa-ge:before{content:"\\F1D1"}.fa-git-square:before{content:"\\F1D2"}.fa-git:before{content:"\\F1D3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\\F1D4"}.fa-tencent-weibo:before{content:"\\F1D5"}.fa-qq:before{content:"\\F1D6"}.fa-wechat:before,.fa-weixin:before{content:"\\F1D7"}.fa-paper-plane:before,.fa-send:before{content:"\\F1D8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\\F1D9"}.fa-history:before{content:"\\F1DA"}.fa-circle-thin:before{content:"\\F1DB"}.fa-header:before{content:"\\F1DC"}.fa-paragraph:before{content:"\\F1DD"}.fa-sliders:before{content:"\\F1DE"}.fa-share-alt:before{content:"\\F1E0"}.fa-share-alt-square:before{content:"\\F1E1"}.fa-bomb:before{content:"\\F1E2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\\F1E3"}.fa-tty:before{content:"\\F1E4"}.fa-binoculars:before{content:"\\F1E5"}.fa-plug:before{content:"\\F1E6"}.fa-slideshare:before{content:"\\F1E7"}.fa-twitch:before{content:"\\F1E8"}.fa-yelp:before{content:"\\F1E9"}.fa-newspaper-o:before{content:"\\F1EA"}.fa-wifi:before{content:"\\F1EB"}.fa-calculator:before{content:"\\F1EC"}.fa-paypal:before{content:"\\F1ED"}.fa-google-wallet:before{content:"\\F1EE"}.fa-cc-visa:before{content:"\\F1F0"}.fa-cc-mastercard:before{content:"\\F1F1"}.fa-cc-discover:before{content:"\\F1F2"}.fa-cc-amex:before{content:"\\F1F3"}.fa-cc-paypal:before{content:"\\F1F4"}.fa-cc-stripe:before{content:"\\F1F5"}.fa-bell-slash:before{content:"\\F1F6"}.fa-bell-slash-o:before{content:"\\F1F7"}.fa-trash:before{content:"\\F1F8"}.fa-copyright:before{content:"\\F1F9"}.fa-at:before{content:"\\F1FA"}.fa-eyedropper:before{content:"\\F1FB"}.fa-paint-brush:before{content:"\\F1FC"}.fa-birthday-cake:before{content:"\\F1FD"}.fa-area-chart:before{content:"\\F1FE"}.fa-pie-chart:before{content:"\\F200"}.fa-line-chart:before{content:"\\F201"}.fa-lastfm:before{content:"\\F202"}.fa-lastfm-square:before{content:"\\F203"}.fa-toggle-off:before{content:"\\F204"}.fa-toggle-on:before{content:"\\F205"}.fa-bicycle:before{content:"\\F206"}.fa-bus:before{content:"\\F207"}.fa-ioxhost:before{content:"\\F208"}.fa-angellist:before{content:"\\F209"}.fa-cc:before{content:"\\F20A"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\\F20B"}.fa-meanpath:before{content:"\\F20C"}.fa-buysellads:before{content:"\\F20D"}.fa-connectdevelop:before{content:"\\F20E"}.fa-dashcube:before{content:"\\F210"}.fa-forumbee:before{content:"\\F211"}.fa-leanpub:before{content:"\\F212"}.fa-sellsy:before{content:"\\F213"}.fa-shirtsinbulk:before{content:"\\F214"}.fa-simplybuilt:before{content:"\\F215"}.fa-skyatlas:before{content:"\\F216"}.fa-cart-plus:before{content:"\\F217"}.fa-cart-arrow-down:before{content:"\\F218"}.fa-diamond:before{content:"\\F219"}.fa-ship:before{content:"\\F21A"}.fa-user-secret:before{content:"\\F21B"}.fa-motorcycle:before{content:"\\F21C"}.fa-street-view:before{content:"\\F21D"}.fa-heartbeat:before{content:"\\F21E"}.fa-venus:before{content:"\\F221"}.fa-mars:before{content:"\\F222"}.fa-mercury:before{content:"\\F223"}.fa-intersex:before,.fa-transgender:before{content:"\\F224"}.fa-transgender-alt:before{content:"\\F225"}.fa-venus-double:before{content:"\\F226"}.fa-mars-double:before{content:"\\F227"}.fa-venus-mars:before{content:"\\F228"}.fa-mars-stroke:before{content:"\\F229"}.fa-mars-stroke-v:before{content:"\\F22A"}.fa-mars-stroke-h:before{content:"\\F22B"}.fa-neuter:before{content:"\\F22C"}.fa-genderless:before{content:"\\F22D"}.fa-facebook-official:before{content:"\\F230"}.fa-pinterest-p:before{content:"\\F231"}.fa-whatsapp:before{content:"\\F232"}.fa-server:before{content:"\\F233"}.fa-user-plus:before{content:"\\F234"}.fa-user-times:before{content:"\\F235"}.fa-bed:before,.fa-hotel:before{content:"\\F236"}.fa-viacoin:before{content:"\\F237"}.fa-train:before{content:"\\F238"}.fa-subway:before{content:"\\F239"}.fa-medium:before{content:"\\F23A"}.fa-y-combinator:before,.fa-yc:before{content:"\\F23B"}.fa-optin-monster:before{content:"\\F23C"}.fa-opencart:before{content:"\\F23D"}.fa-expeditedssl:before{content:"\\F23E"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\\F240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\\F241"}.fa-battery-2:before,.fa-battery-half:before{content:"\\F242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\\F243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\\F244"}.fa-mouse-pointer:before{content:"\\F245"}.fa-i-cursor:before{content:"\\F246"}.fa-object-group:before{content:"\\F247"}.fa-object-ungroup:before{content:"\\F248"}.fa-sticky-note:before{content:"\\F249"}.fa-sticky-note-o:before{content:"\\F24A"}.fa-cc-jcb:before{content:"\\F24B"}.fa-cc-diners-club:before{content:"\\F24C"}.fa-clone:before{content:"\\F24D"}.fa-balance-scale:before{content:"\\F24E"}.fa-hourglass-o:before{content:"\\F250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\\F251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\\F252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\\F253"}.fa-hourglass:before{content:"\\F254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\\F255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\\F256"}.fa-hand-scissors-o:before{content:"\\F257"}.fa-hand-lizard-o:before{content:"\\F258"}.fa-hand-spock-o:before{content:"\\F259"}.fa-hand-pointer-o:before{content:"\\F25A"}.fa-hand-peace-o:before{content:"\\F25B"}.fa-trademark:before{content:"\\F25C"}.fa-registered:before{content:"\\F25D"}.fa-creative-commons:before{content:"\\F25E"}.fa-gg:before{content:"\\F260"}.fa-gg-circle:before{content:"\\F261"}.fa-tripadvisor:before{content:"\\F262"}.fa-odnoklassniki:before{content:"\\F263"}.fa-odnoklassniki-square:before{content:"\\F264"}.fa-get-pocket:before{content:"\\F265"}.fa-wikipedia-w:before{content:"\\F266"}.fa-safari:before{content:"\\F267"}.fa-chrome:before{content:"\\F268"}.fa-firefox:before{content:"\\F269"}.fa-opera:before{content:"\\F26A"}.fa-internet-explorer:before{content:"\\F26B"}.fa-television:before,.fa-tv:before{content:"\\F26C"}.fa-contao:before{content:"\\F26D"}.fa-500px:before{content:"\\F26E"}.fa-amazon:before{content:"\\F270"}.fa-calendar-plus-o:before{content:"\\F271"}.fa-calendar-minus-o:before{content:"\\F272"}.fa-calendar-times-o:before{content:"\\F273"}.fa-calendar-check-o:before{content:"\\F274"}.fa-industry:before{content:"\\F275"}.fa-map-pin:before{content:"\\F276"}.fa-map-signs:before{content:"\\F277"}.fa-map-o:before{content:"\\F278"}.fa-map:before{content:"\\F279"}.fa-commenting:before{content:"\\F27A"}.fa-commenting-o:before{content:"\\F27B"}.fa-houzz:before{content:"\\F27C"}.fa-vimeo:before{content:"\\F27D"}.fa-black-tie:before{content:"\\F27E"}.fa-fonticons:before{content:"\\F280"}.fa-reddit-alien:before{content:"\\F281"}.fa-edge:before{content:"\\F282"}.fa-credit-card-alt:before{content:"\\F283"}.fa-codiepie:before{content:"\\F284"}.fa-modx:before{content:"\\F285"}.fa-fort-awesome:before{content:"\\F286"}.fa-usb:before{content:"\\F287"}.fa-product-hunt:before{content:"\\F288"}.fa-mixcloud:before{content:"\\F289"}.fa-scribd:before{content:"\\F28A"}.fa-pause-circle:before{content:"\\F28B"}.fa-pause-circle-o:before{content:"\\F28C"}.fa-stop-circle:before{content:"\\F28D"}.fa-stop-circle-o:before{content:"\\F28E"}.fa-shopping-bag:before{content:"\\F290"}.fa-shopping-basket:before{content:"\\F291"}.fa-hashtag:before{content:"\\F292"}.fa-bluetooth:before{content:"\\F293"}.fa-bluetooth-b:before{content:"\\F294"}.fa-percent:before{content:"\\F295"}.fa-gitlab:before{content:"\\F296"}.fa-wpbeginner:before{content:"\\F297"}.fa-wpforms:before{content:"\\F298"}.fa-envira:before{content:"\\F299"}.fa-universal-access:before{content:"\\F29A"}.fa-wheelchair-alt:before{content:"\\F29B"}.fa-question-circle-o:before{content:"\\F29C"}.fa-blind:before{content:"\\F29D"}.fa-audio-description:before{content:"\\F29E"}.fa-volume-control-phone:before{content:"\\F2A0"}.fa-braille:before{content:"\\F2A1"}.fa-assistive-listening-systems:before{content:"\\F2A2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\\F2A3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\\F2A4"}.fa-glide:before{content:"\\F2A5"}.fa-glide-g:before{content:"\\F2A6"}.fa-sign-language:before,.fa-signing:before{content:"\\F2A7"}.fa-low-vision:before{content:"\\F2A8"}.fa-viadeo:before{content:"\\F2A9"}.fa-viadeo-square:before{content:"\\F2AA"}.fa-snapchat:before{content:"\\F2AB"}.fa-snapchat-ghost:before{content:"\\F2AC"}.fa-snapchat-square:before{content:"\\F2AD"}.fa-pied-piper:before{content:"\\F2AE"}.fa-first-order:before{content:"\\F2B0"}.fa-yoast:before{content:"\\F2B1"}.fa-themeisle:before{content:"\\F2B2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\\F2B3"}.fa-fa:before,.fa-font-awesome:before{content:"\\F2B4"}.fa-handshake-o:before{content:"\\F2B5"}.fa-envelope-open:before{content:"\\F2B6"}.fa-envelope-open-o:before{content:"\\F2B7"}.fa-linode:before{content:"\\F2B8"}.fa-address-book:before{content:"\\F2B9"}.fa-address-book-o:before{content:"\\F2BA"}.fa-address-card:before,.fa-vcard:before{content:"\\F2BB"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\\F2BC"}.fa-user-circle:before{content:"\\F2BD"}.fa-user-circle-o:before{content:"\\F2BE"}.fa-user-o:before{content:"\\F2C0"}.fa-id-badge:before{content:"\\F2C1"}.fa-drivers-license:before,.fa-id-card:before{content:"\\F2C2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\\F2C3"}.fa-quora:before{content:"\\F2C4"}.fa-free-code-camp:before{content:"\\F2C5"}.fa-telegram:before{content:"\\F2C6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\\F2C7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\\F2C8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\\F2C9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\\F2CA"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\\F2CB"}.fa-shower:before{content:"\\F2CC"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\\F2CD"}.fa-podcast:before{content:"\\F2CE"}.fa-window-maximize:before{content:"\\F2D0"}.fa-window-minimize:before{content:"\\F2D1"}.fa-window-restore:before{content:"\\F2D2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\\F2D3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\\F2D4"}.fa-bandcamp:before{content:"\\F2D5"}.fa-grav:before{content:"\\F2D6"}.fa-etsy:before{content:"\\F2D7"}.fa-imdb:before{content:"\\F2D8"}.fa-ravelry:before{content:"\\F2D9"}.fa-eercast:before{content:"\\F2DA"}.fa-microchip:before{content:"\\F2DB"}.fa-snowflake-o:before{content:"\\F2DC"}.fa-superpowers:before{content:"\\F2DD"}.fa-wpexplorer:before{content:"\\F2DE"}.fa-meetup:before{content:"\\F2E0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}',""]); -},function(A,M,t){M=A.exports=t(138)(),M.push([A.id,'*,:after,:before{box-sizing:border-box}body{font-family:Lato,sans-serif;font-size:15px;line-height:1.42857143;color:#8e8e8e;background-color:#edecec}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#46a5e0}a,a:focus,a:hover{text-decoration:none}a:focus,a:hover{color:#1f7fba}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#edecec;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:15px;text-align:left;background-color:#fff;border:1px solid transparent;border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:rgba(0,0,0,.08)}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#8e8e8e;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#333;background-color:rgba(0,0,0,.05)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#333;text-decoration:none;outline:0;background-color:rgba(0,0,0,.075)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#e4e4e4}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:13px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid\\9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu>li>a{text-align:right}.navbar-right .dropdown-menu-left{left:0;right:auto}}.modal,.modal-open{overflow:hidden}.modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translateY(-25%);transform:translateY(-25%);-webkit-transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0);transform:translate(0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid transparent;border-radius:6px;box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:rgba(0,0,0,.1)}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:30px 35px 0;border-bottom:1px solid transparent}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:transparent}.modal-body{position:relative;padding:30px 35px}.modal-footer{padding:30px 35px;text-align:right;border-top:1px solid transparent}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:400px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:Lato,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:13px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px}.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow{bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{left:5px}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}:active,:focus{outline:0}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body,html{min-height:100%}a{-webkit-transition:color;transition:color;-webkit-transition-duration:.3s;transition-duration:.3s}button{border:0}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translateY(-20px)}to{opacity:1;-webkit-transform:translateY(0)}}@keyframes fadeInDown{0%{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translateY(20px)}to{opacity:1;-webkit-transform:translateY(0)}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeOut{0%{opacity:1}to{opacity:0}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1;-webkit-transform:translateY(0)}to{opacity:0;-webkit-transform:translateY(20px)}}@keyframes fadeOutDown{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(20px)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutUp{0%{opacity:1;-webkit-transform:translateY(0)}to{opacity:0;-webkit-transform:translateY(-20px)}}@keyframes fadeOutUp{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-20px)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.text-center{text-align:center!important}.text-left{text-align:left!important}.text-right{text-align:right!important}.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.row:after,.row:before{content:" ";display:table}.clearfix:after,.container-fluid:after,.container:after,.modal-footer:after,.modal-header:after,.row:after{clear:both}.pull-right{float:right!important}.pull-left{float:left!important}.p-relative{position:relative}.m-0{margin:0!important}.m-t-0{margin-top:0!important}.m-b-0{margin-bottom:0!important}.m-l-0{margin-left:0!important}.m-r-0{margin-right:0!important}.m-5{margin:5px!important}.m-t-5{margin-top:5px!important}.m-b-5{margin-bottom:5px!important}.m-l-5{margin-left:5px!important}.m-r-5{margin-right:5px!important}.m-10{margin:10px!important}.m-t-10{margin-top:10px!important}.m-b-10{margin-bottom:10px!important}.m-l-10{margin-left:10px!important}.m-r-10{margin-right:10px!important}.m-15{margin:15px!important}.m-t-15{margin-top:15px!important}.m-b-15{margin-bottom:15px!important}.m-l-15{margin-left:15px!important}.m-r-15{margin-right:15px!important}.m-20{margin:20px!important}.m-t-20{margin-top:20px!important}.m-b-20{margin-bottom:20px!important}.m-l-20{margin-left:20px!important}.m-r-20{margin-right:20px!important}.m-25{margin:25px!important}.m-t-25{margin-top:25px!important}.m-b-25{margin-bottom:25px!important}.m-l-25{margin-left:25px!important}.m-r-25{margin-right:25px!important}.m-30{margin:30px!important}.m-t-30{margin-top:30px!important}.m-b-30{margin-bottom:30px!important}.m-l-30{margin-left:30px!important}.m-r-30{margin-right:30px!important}.p-0{padding:0!important}.p-t-0{padding-top:0!important}.p-b-0{padding-bottom:0!important}.p-l-0{padding-left:0!important}.p-r-0{padding-right:0!important}.p-5{padding:5px!important}.p-t-5{padding-top:5px!important}.p-b-5{padding-bottom:5px!important}.p-l-5{padding-left:5px!important}.p-r-5{padding-right:5px!important}.p-10{padding:10px!important}.p-t-10{padding-top:10px!important}.p-b-10{padding-bottom:10px!important}.p-l-10{padding-left:10px!important}.p-r-10{padding-right:10px!important}.p-15{padding:15px!important}.p-t-15{padding-top:15px!important}.p-b-15{padding-bottom:15px!important}.p-l-15{padding-left:15px!important}.p-r-15{padding-right:15px!important}.p-20{padding:20px!important}.p-t-20{padding-top:20px!important}.p-b-20{padding-bottom:20px!important}.p-l-20{padding-left:20px!important}.p-r-20{padding-right:20px!important}.p-25{padding:25px!important}.p-t-25{padding-top:25px!important}.p-b-25{padding-bottom:25px!important}.p-l-25{padding-left:25px!important}.p-r-25{padding-right:25px!important}.p-30{padding:30px!important}.p-t-30{padding-top:30px!important}.p-b-30{padding-bottom:30px!important}.p-l-30{padding-left:30px!important}.p-r-30{padding-right:30px!important}@font-face{font-family:Lato;src:url('+t(514)+') format("woff2"),url('+t(513)+') format("woff");font-weight:400;font-style:normal}.form-control{border:0;border-bottom:1px solid #eee;color:#32393f;padding:5px;width:100%;font-size:13px;background-color:transparent}select.form-control{-webkit-appearance:none;-moz-appearance:none;border-radius:0;background:url('+t(517)+') no-repeat bottom 7px right}.input-group{position:relative}.input-group:not(:last-child){margin-bottom:25px}.input-group label:not(.ig-label){font-size:13px;display:block;margin-bottom:10px}.ig-label{position:absolute;text-align:center;bottom:7px;left:0;width:100%;-webkit-transition:all;transition:all;-webkit-transition-duration:.25s;transition-duration:.25s;padding:2px 0 3px;border-radius:2px;font-weight:400}.ig-helpers{z-index:1;width:100%;left:0}.ig-helpers,.ig-helpers:after,.ig-helpers:before{position:absolute;height:2px;bottom:0}.ig-helpers:after,.ig-helpers:before{content:"";width:0;-webkit-transition:all;transition:all;-webkit-transition-duration:.25s;transition-duration:.25s;background-color:#03a9f4}.ig-helpers:before{left:50%}.ig-helpers:after{right:50%}.ig-text{width:100%;height:40px;border:0;background:transparent;text-align:center;position:relative;z-index:1;border-bottom:1px solid #eee;color:#32393f;font-size:13px}.ig-text:focus+.ig-helpers:after,.ig-text:focus+.ig-helpers:before{width:50%}.ig-text:disabled~.ig-label,.ig-text:focus~.ig-label,.ig-text:valid~.ig-label{bottom:35px;font-size:13px;z-index:1}.ig-text:disabled{opacity:.5;filter:alpha(opacity=50)}.ig-dark .ig-text{color:#fff;border-color:hsla(0,0%,100%,.1)}.ig-dark .ig-helpers:after,.ig-dark .ig-helpers:before{background-color:#dfdfdf;height:1px}.ig-left .ig-label,.ig-left .ig-text{text-align:left}.ig-error .ig-label{color:#e23f3f}.ig-error .ig-helpers i:first-child,.ig-error .ig-helpers i:first-child:after,.ig-error .ig-helpers i:first-child:before{background:rgba(226,63,63,.43)}.ig-error .ig-helpers i:last-child,.ig-error .ig-helpers i:last-child:after,.ig-error .ig-helpers i:last-child:before{background:#e23f3f!important}.ig-error:after{content:"\\F05A";font-family:FontAwesome;position:absolute;top:17px;right:9px;font-size:20px;color:#d33d3e}.ig-search:before{font-family:fontAwesome;content:"\\F002";font-size:15px;position:absolute;left:2px;top:8px}.ig-search .ig-text{padding-left:25px}.set-expire{border:1px solid #eee;margin:35px 0 30px}.set-expire-item{padding:9px 5px 3px;position:relative;display:table-cell;width:1%;text-align:center}.set-expire-item:not(:last-child){border-right:1px solid #eee}.set-expire-title{font-size:10px;text-transform:uppercase}.set-expire-value{display:inline-block;overflow:hidden;position:relative;left:-8px}.set-expire-value input{font-size:20px;text-align:center;position:relative;right:-15px;border:0;color:#333;padding:0;height:25px;width:100%;font-weight:400}.set-expire-decrease,.set-expire-increase{position:absolute;width:20px;height:20px;background:url('+t(515)+') no-repeat 50%;background-size:85%;left:50%;margin-left:-10px;opacity:.2;filter:alpha(opacity=20);cursor:pointer}.set-expire-decrease:hover,.set-expire-increase:hover{opacity:.5;filter:alpha(opacity=50)}.set-expire-increase{top:-25px}.set-expire-decrease{bottom:-27px;-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}.btn{border:0;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:2px;text-align:center;-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}.btn:focus,.btn:hover{opacity:.9;filter:alpha(opacity=90)}.btn-block{display:block;width:100%}.btn-link{color:#545454;background-color:#eee}.btn-link:focus,.btn-link:hover{color:#545454;background-color:#dfdfdf}.btn-danger{color:#fff;background-color:#ff726f}.btn-danger:focus,.btn-danger:hover{color:#fff;background-color:#ff5450}.btn-primary{color:#fff;background-color:#50b2ff}.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#31a5ff}.btn-success{color:#fff;background-color:#33d46f}.btn-success:focus,.btn-success:hover{color:#fff;background-color:#28c061}.close{right:15px;font-weight:400;opacity:1;font-size:18px;position:absolute;text-align:center;top:16px;z-index:1;padding:0;border:0;background-color:transparent}.close span{width:25px;height:25px;display:block;border-radius:50%;line-height:24px;text-shadow:none}.close:not(.close-alt) span{background-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.8)}.close:not(.close-alt):focus span,.close:not(.close-alt):hover span{background-color:hsla(0,0%,100%,.2);color:#fff}.close-alt span{background-color:#efefef;color:#989898}.close-alt:focus span,.close-alt:hover span{background-color:#e8e8e8;color:#7b7b7b}.hidden{display:none!important}.copy-text input{width:100%;border-radius:1px;border:1px solid #eee;padding:7px 12px;font-size:13px;line-height:100%;cursor:text;-webkit-transition:border-color;transition:border-color;-webkit-transition-duration:.3s;transition-duration:.3s}.copy-text input:hover{border-color:#e1e1e1}.share-availability{margin-bottom:40px}.share-availability:after,.share-availability:before{position:absolute;bottom:-30px;font-size:10px}.share-availability:before{content:"01 Sec";left:0}.share-availability:after{content:"7 days";right:0}.login{height:100vh;min-height:500px;background:#32393f;text-align:center}.login:before{height:calc(100% - 110px);width:1px;content:""}.l-wrap,.login:before{display:inline-block;vertical-align:middle}.l-wrap{width:80%;max-width:500px;margin-top:-50px}.l-wrap.toggled{display:inline-block}.l-wrap .input-group:not(:last-child){margin-bottom:40px}.l-footer{height:110px;padding:0 50px}.lf-logo{float:right}.lf-logo img{width:40px}.lf-server{float:left;color:hsla(0,0%,100%,.4);font-size:20px;font-weight:400;padding-top:40px}@media (max-width:768px){.lf-logo,.lf-server{float:none;display:block;text-align:center;width:100%}.lf-logo{margin-bottom:5px}.lf-server{font-size:15px}}.lw-btn{width:50px;height:50px;border:1px solid #fff;display:inline-block;border-radius:50%;font-size:22px;color:#fff;-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s;opacity:.3;background-color:transparent;line-height:45px;padding:0}.lw-btn:hover{color:#fff;opacity:.8;border-color:#fff}.lw-btn i{display:block;width:100%;padding-left:3px}input:-webkit-autofill{-webkit-box-shadow:0 0 0 50px #32393f inset!important;-webkit-text-fill-color:#fff!important}.fe-header{padding:45px 55px 20px}@media (min-width:992px){.fe-header{position:relative}}@media (max-width:667px){.fe-header{padding:25px 25px 20px}}.fe-header h2{font-size:16px;font-weight:400;margin:0}.fe-header h2>span{margin-bottom:7px;display:inline-block}.fe-header h2>span:not(:first-child):before{content:"/";margin:0 4px;color:#8e8e8e}.fe-header p{margin-top:7px}.feh-usage{margin-top:12px;max-width:285px}@media (max-width:667px){.feh-usage{max-width:100%;font-size:12px}}.feh-usage>ul{margin-top:7px;list-style:none;padding:0}.feh-usage>ul>li{padding-right:0;display:inline-block}.fehu-chart{height:5px;background:#eee;position:relative;border-radius:2px;overflow:hidden}.fehu-chart>div{position:absolute;left:0;height:100%;background:#46a5e0}.feh-actions{list-style:none;padding:0;margin:0;position:absolute;right:35px;top:30px;z-index:11}@media (max-width:991px){.feh-actions{top:7px;right:10px;position:fixed}}.feh-actions>li{display:inline-block;text-align:right;vertical-align:top;line-height:100%}.feh-actions>li>.btn-group>button,.feh-actions>li>a{display:block;height:45px;min-width:45px;text-align:center;border-radius:50%;padding:0;border:0;background:none}@media (min-width:992px){.feh-actions>li>.btn-group>button,.feh-actions>li>a{color:#7b7b7b;font-size:21px;line-height:45px;-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}.feh-actions>li>.btn-group>button:hover,.feh-actions>li>a:hover{background:rgba(0,0,0,.09)}}@media (max-width:991px){.feh-actions>li>.btn-group>button,.feh-actions>li>a{background:url('+t(237)+') no-repeat 50%}.feh-actions>li>.btn-group>button .fa-reorder,.feh-actions>li>a .fa-reorder{display:none}}@media (max-width:991px){.fe-header-mobile{background-color:#32393f;padding:10px 50px 9px 12px;text-align:center;position:fixed;z-index:10;box-shadow:0 0 10px rgba(0,0,0,.3);left:0;top:0;width:100%}.fe-header-mobile .mh-logo{height:35px;position:relative;top:4px}.feh-trigger{width:41px;height:41px;cursor:pointer;float:left;position:relative;text-align:center}.feh-trigger:after,.feh-trigger:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;border-radius:50%}.feh-trigger:after{z-index:1}.feh-trigger:before{background:hsla(0,0%,100%,.1);-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:scale(0);transform:scale(0)}.feht-toggled:before{-webkit-transform:scale(1);transform:scale(1)}.feht-toggled .feht-lines{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.feht-toggled .feht-lines>div.top{width:12px;transform:translateX(8px) translateY(1px) rotate(45deg);-webkit-transform:translateX(8px) translateY(1px) rotate(45deg)}.feht-toggled .feht-lines>div.bottom{width:12px;transform:translateX(8px) translateY(-1px) rotate(-45deg);-webkit-transform:translateX(8px) translateY(-1px) rotate(-45deg)}.feht-lines,.feht-lines>div{-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}.feht-lines{width:18px;height:12px;display:inline-block;margin-top:14px}.feht-lines>div{background-color:#eaeaea;width:18px;height:2px}.feht-lines>div.center{margin:3px 0}}.fe-sidebar{width:300px;background-color:#32393f;position:fixed;height:100%;overflow:hidden;padding:35px}@media (min-width:992px){.fe-sidebar{-webkit-transform:translateZ(0);transform:translateZ(0)}}@media (max-width:991px){.fe-sidebar{padding-top:85px;z-index:9;box-shadow:0 0 10px rgba(0,0,0,.65);-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:translate3d(-315px,0,0);transform:translate3d(-315px,0,0)}.fe-sidebar.toggled{-webkit-transform:translateZ(0);transform:translateZ(0)}}.fe-sidebar a{color:hsla(0,0%,100%,.58)}.fe-sidebar a:hover{color:#fff}.fes-header{margin-bottom:40px}.fes-header h2,.fes-header img{float:left}.fes-header h2{margin:13px 0 0 10px;font-weight:400}.fes-header img{width:32px}.fesl-inner{height:calc(100vh - 260px);overflow:auto;padding:0;margin:0 -35px}.fesl-inner li{position:relative}.fesl-inner li>a{display:block;padding:10px 40px 12px 65px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fesl-inner li>a:before{font-family:FontAwesome;content:"\\F0A0";font-size:17px;position:absolute;top:10px;left:35px;opacity:.8;filter:alpha(opacity=80)}.fesl-inner li>a.fesli-loading:before{content:"";width:20px;height:20px;border-radius:50%;-webkit-animation-name:zoomIn;animation-name:zoomIn;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;border:2px solid hsla(0,0%,100%,.1);border-bottom-color:hsla(0,0%,100%,.5);position:absolute;z-index:1;-webkit-animation:zoomIn .25s,spin .7s .25s infinite linear;animation:zoomIn .25s,spin .7s .25s infinite linear;left:32px;top:0;bottom:0;margin:auto}.fesl-inner li.active{background-color:rgba(0,0,0,.2)}.fesl-inner li.active>a{color:#fff}.fesl-inner li:not(.active):hover{background-color:rgba(0,0,0,.1)}.fesl-inner li:not(.active):hover>a{color:#fff}.fesl-inner li:hover .fesli-trigger{opacity:.6;filter:alpha(opacity=60)}.fesl-inner li:hover .fesli-trigger:hover{opacity:1;filter:alpha(opacity=100)}.fesl-inner ul{list-style:none;padding:0;margin:0}.fesl-inner:hover .scrollbar-vertical{opacity:1}.fesli-trigger{filter:alpha(opacity=0);-webkit-transition:all;transition:all;-webkit-transition-duration:.2s;transition-duration:.2s;top:0;right:0;width:40px;cursor:pointer;background:url('+t(237)+') no-repeat 0}.fesli-trigger,.scrollbar-vertical{opacity:0;position:absolute;height:100%}.scrollbar-vertical{right:5px;width:4px;-webkit-transition:opacity;transition:opacity;-webkit-transition-duration:.3s;transition-duration:.3s}.scrollbar-vertical div{border-radius:1px!important;background-color:#6a6a6a!important}.fes-host{position:fixed;left:0;bottom:0;z-index:1;background:#32393f;color:hsla(0,0%,100%,.4);font-size:15px;font-weight:400;width:300px;padding:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fes-host>i{margin-right:10px}.fesl-row{padding-right:40px;padding-top:5px;padding-bottom:5px;position:relative}@media (min-width:668px){.fesl-row{display:flex;flex-flow:row nowrap;justify-content:space-between}}.fesl-row:after,.fesl-row:before{content:" ";display:table}.fesl-row:after{clear:both}@media (min-width:668px){header.fesl-row{margin-bottom:20px;border-bottom:1px solid #f0f0f0;padding-left:40px}header.fesl-row .fesl-item,header.fesl-row .fesli-sort{-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}header.fesl-row .fesl-item{cursor:pointer;color:#8e8e8e;font-weight:500;margin-bottom:-5px}header.fesl-row .fesl-item>.fesli-sort{float:right;margin:4px 0 0;opacity:0;filter:alpha(opacity=0);color:#32393f;font-size:14px}header.fesl-row .fesl-item:hover:not(.fi-actions){background:#f5f5f5;color:#32393f}header.fesl-row .fesl-item:hover:not(.fi-actions)>.fesli-sort{opacity:.5;filter:alpha(opacity=50)}}@media (max-width:667px){header.fesl-row{display:none}}div.fesl-row{padding-left:85px;border-bottom:1px solid transparent;cursor:default}@media (max-width:667px){div.fesl-row{padding-left:70px;padding-right:45px}}div.fesl-row:nth-child(2n){background-color:#fafafa}div.fesl-row:hover{background-color:#fbf7dc}div.fesl-row[data-type]:before{font-family:fontAwesome;width:35px;height:35px;text-align:center;line-height:35px;position:absolute;border-radius:50%;font-size:16px;left:50px;top:9px;color:#fff}@media (max-width:667px){div.fesl-row[data-type]:before{left:20px}}@media (max-width:667px){div.fesl-row[data-type=folder] .fesl-item.fi-name{padding-top:10px;padding-bottom:7px}div.fesl-row[data-type=folder] .fesl-item.fi-modified,div.fesl-row[data-type=folder] .fesl-item.fi-size{display:none}}div.fesl-row[data-type=folder]:before{content:"\\F114";background-color:#a1d6dd}div.fesl-row[data-type=pdf]:before{content:"\\F1C1";background-color:#fa7775}div.fesl-row[data-type=zip]:before{content:"\\F1C6";background-color:#427089}div.fesl-row[data-type=audio]:before{content:"\\F1C7";background-color:#009688}div.fesl-row[data-type=code]:before{content:"\\F1C9";background-color:#997867}div.fesl-row[data-type=excel]:before{content:"\\F1C3";background-color:#64c866}div.fesl-row[data-type=image]:before{content:"\\F1C5";background-color:#f06292}div.fesl-row[data-type=video]:before{content:"\\F1C8";background-color:#f8c363}div.fesl-row[data-type=other]:before{content:"\\F016";background-color:#afafaf}div.fesl-row[data-type=text]:before{content:"\\F0F6";background-color:#8a8a8a}div.fesl-row[data-type=doc]:before{content:"\\F1C2";background-color:#2196f5}div.fesl-row[data-type=presentation]:before{content:"\\F1C4";background-color:#896ea6}div.fesl-row.fesl-loading:before{content:""}div.fesl-row.fesl-loading:after{content:"";width:20px;height:20px;border-radius:50%;-webkit-animation-name:zoomIn;animation-name:zoomIn;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;border:2px solid hsla(0,0%,100%,.5);border-bottom-color:#fff;position:absolute;z-index:1;-webkit-animation:zoomIn .25s,spin .7s .25s infinite linear;animation:zoomIn .25s,spin .7s .25s infinite linear;left:57px;top:17px}@media (max-width:667px){div.fesl-row.fesl-loading:after{left:27px}}.fesl-item{display:block}.fesl-item a{color:#818181}@media (min-width:668px){.fesl-item:not(.fi-actions){text-overflow:ellipsis;padding:10px 15px;white-space:nowrap;overflow:hidden}.fesl-item.fi-name{flex:3}.fesl-item.fi-size{width:140px}.fesl-item.fi-modified{width:190px}.fesl-item.fi-actions{width:40px}}@media (max-width:667px){.fesl-item{padding:0}.fesl-item.fi-name{width:100%;margin-bottom:3px}.fesl-item.fi-modified,.fesl-item.fi-size{font-size:12px;color:#b5b5b5;float:left}.fesl-item.fi-modified{max-width:72px;white-space:nowrap;overflow:hidden}.fesl-item.fi-size{margin-right:10px}.fesl-item.fi-actions{position:absolute;top:5px;right:10px}}.fia-toggle{height:36px;width:36px;background:transparent url('+t(516)+') no-repeat 50%;position:relative;top:3px;opacity:.4;filter:alpha(opacity=40)}.fia-toggle:hover{opacity:.7;filter:alpha(opacity=70)}.fi-actions .dropdown-menu{background-color:transparent;box-shadow:none;padding:0;right:38px;left:auto;margin:0;height:100%;text-align:right}.fi-actions .dropdown.open .dropdown-menu .fiad-action{right:0}.fiad-action{height:35px;width:35px;background:#ffc107;display:inline-block;border-radius:50%;text-align:center;line-height:35px;font-weight:400;position:relative;top:4px;margin-left:5px;-webkit-animation-name:fiad-action-anim;animation-name:fiad-action-anim;-webkit-transform-origin:center center;transform-origin:center center;-webkit-backface-visibility:none;backface-visibility:none;box-shadow:0 2px 4px rgba(0,0,0,.1)}.fiad-action:nth-child(2){-webkit-animation-duration:.1s;animation-duration:.1s}.fiad-action:first-child{-webkit-animation-duration:.25s;animation-duration:.25s}.fiad-action>i{font-size:14px;color:#fff}.fiad-action:hover{background-color:#f7b900}@-webkit-keyframes fiad-action-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0);right:-20px}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100);right:0}}@keyframes fiad-action-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0);right:-20px}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100);right:0}}.file-explorer{background-color:#fff;position:relative;height:100%}.file-explorer.toggled{height:100vh;overflow:hidden}.fe-body{min-height:100vh;overflow:auto}@media (min-width:992px){.fe-body{padding:0 0 40px 300px}}@media (max-width:991px){.fe-body{padding:75px 0 80px}}.feb-actions{position:fixed;bottom:30px;right:30px}.feb-actions .dropdown-menu{min-width:55px;width:55px;text-align:center;background:transparent;box-shadow:none;margin:0}.feb-actions.open .feba-btn{-webkit-transform:scale(1);transform:scale(1)}.feb-actions.open .feba-btn:first-child{-webkit-animation-name:feba-btn-anim;animation-name:feba-btn-anim;-webkit-animation-duration:.3s;animation-duration:.3s}.feb-actions.open .feba-btn:last-child{-webkit-animation-name:feba-btn-anim;animation-name:feba-btn-anim;-webkit-animation-duration:.1s;animation-duration:.1s}.feb-actions.open .feba-toggle{background:#ff403c}.feb-actions.open .feba-toggle>span{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.feba-toggle{width:55px;height:55px;line-height:55px;border-radius:50%;background:#ff726f;box-shadow:0 2px 3px rgba(0,0,0,.15);display:inline-block;text-align:center;border:0;padding:0}.feba-toggle span{display:inline-block;height:100%;width:100%}.feba-toggle i{color:#fff;font-size:17px;line-height:58px}.feba-toggle,.feba-toggle>span{-webkit-transition:all;transition:all;-webkit-transition-duration:.25s;transition-duration:.25s;-webkit-backface-visibility:hidden;backface-visibility:hidden}.feba-btn{width:40px;margin-top:10px;height:40px;border-radius:50%;text-align:center;display:inline-block;line-height:40px;box-shadow:0 2px 3px rgba(0,0,0,.15);-webkit-transform:scale(0);transform:scale(0);position:relative}.feba-btn,.feba-btn:focus,.feba-btn:hover{color:#fff}.feba-btn label{width:100%;height:100%;position:absolute;left:0;top:0;cursor:pointer}.feba-bucket{background:#ffc155}.feba-upload{background:#ffc107}@-webkit-keyframes feba-btn-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100)}}@keyframes feba-btn-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100)}}.ie-warning{background-color:#ff5252;width:100%;height:100%;position:fixed;left:0;top:0;text-align:center}.ie-warning:before{width:1px;content:"";height:100%}.ie-warning .iw-inner,.ie-warning:before{display:inline-block;vertical-align:middle}.iw-inner{width:470px;height:300px;background-color:#fff;border-radius:5px;padding:40px;position:relative}.iw-inner ul{list-style:none;padding:0;margin:0;width:230px;margin-left:80px;margin-top:16px}.iw-inner ul>li{float:left}.iw-inner ul>li>a{display:block;padding:10px 15px 7px;font-size:14px;margin:0 1px;border-radius:3px}.iw-inner ul>li>a:hover{background:#eee}.iw-inner ul>li>a img{height:40px;margin-bottom:5px}.iwi-icon{color:#ff5252;font-size:40px;display:block;line-height:100%;margin-bottom:15px}.iwi-skip{position:absolute;left:0;bottom:-35px;width:100%;color:hsla(0,0%,100%,.6);cursor:pointer}.iwi-skip:hover{color:#fff}.dropdown-menu{padding:15px 0;top:0;margin-top:-1px}.dropdown-menu>li>a{padding:8px 20px;font-size:15px}.dropdown-menu>li>a>i{width:20px;position:relative;top:1px}.dropdown-menu-right>li>a{text-align:right}.alert{border:0;position:fixed;max-width:500px;margin:0;box-shadow:0 4px 5px rgba(0,0,0,.1);color:#fff;width:100%;right:20px;border-radius:3px;padding:17px 50px 17px 17px;z-index:10010;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.alert:not(.progress){top:20px}@media (min-width:768px){.alert:not(.progress){left:50%;margin-left:-250px}}.alert.progress{bottom:20px;right:20px}.alert.alert-danger{background:#ff726f}.alert.alert-success{background:#33d46f}.alert.alert-info{background:#50b2ff}@media (max-width:767px){.alert{left:20px;width:calc(100% - 40px);max-width:100%}}.alert .progress{margin:10px 10px 8px 0;height:5px;box-shadow:none;border-radius:1px;background-color:#50b2ff;border-radius:2px;overflow:hidden}.alert .progress-bar{box-shadow:none;background-color:#fff;height:100%}.alert .close{position:absolute;top:15px}@media (min-width:768px){.modal{text-align:center}.modal:before{content:"";height:100%;width:1px}.modal .modal-dialog,.modal:before{display:inline-block;vertical-align:middle}.modal .modal-dialog{text-align:left;margin:10px auto}}.modal-dark .modal-header{color:hsla(0,0%,100%,.4)}.modal-dark .modal-header small{color:hsla(0,0%,100%,.2)}.modal-dark .modal-content{background-color:#32393f}.modal-backdrop{-webkit-animation-name:fadeIn;animation-name:fadeIn;-webkit-animation-fill-mode:both;animation-fill-mode:both}.modal-backdrop,.modal-dialog{-webkit-animation-duration:.2s;animation-duration:.2s}.modal-dialog{-webkit-animation-name:zoomIn;animation-name:zoomIn;-webkit-animation-fill-mode:both;animation-fill-mode:both}.modal-header{color:#333;position:relative}.modal-header small{display:block;text-transform:none;font-size:12px;margin-top:5px;color:#a8a8a8}.modal-content{border-radius:3px;box-shadow:none}.modal-footer{padding:0 30px 30px}.modal-confirm .modal-dialog,.modal-footer{text-align:center}.mc-icon{margin:0 0 10px}.mc-icon>i{font-size:60px}.mci-red{color:#ff8f8f}.mci-amber{color:#ffc107}.mci-green{color:#64e096}.mc-text{color:#333}.mc-sub{color:#bdbdbd;margin-top:5px;font-size:13px}@media (max-width:767px){.modal-about{text-align:center}.modal-about .modal-dialog{max-width:400px;width:90%;margin:20px auto 0}}.ma-inner{display:flex;flex-direction:row;align-items:center;min-height:350px;position:relative}@media (min-width:768px){.ma-inner:before{content:"";width:150px;height:100%;top:0;left:0;position:absolute;border-radius:3px 0 0 3px;background-color:#23282c}}.mai-item:first-child{width:150px;text-align:center}.mai-item:last-child{flex:4;padding:30px}.maii-logo{width:70px;position:relative}.maii-list{list-style:none;padding:0}.maii-list>li{margin-bottom:15px}.maii-list>li div{color:hsla(0,0%,100%,.8);text-transform:uppercase;font-size:14px}.maii-list>li small{font-size:13px;color:hsla(0,0%,100%,.4)}.toggle-password{position:absolute;bottom:30px;right:35px;width:30px;height:30px;border:1px solid #eee;border-radius:0;text-align:center;cursor:pointer;z-index:10;background-color:#fff;padding-top:5px}.toggle-password.toggled{background:#eee}.pm-body{padding-bottom:30px}.pmb-header{margin-bottom:35px}.pmb-list{display:flex;flex-flow:row nowrap;align-items:center;justify-content:center;padding:10px 35px}.pmb-list:nth-child(2n){background-color:#f7f7f7}.pmb-list .form-control{padding-left:0;padding-right:0}header.pmb-list{margin:20px 0 10px}.pmbl-item{display:block;font-size:13px}.pmbl-item:first-child{flex:2}.pmbl-item:nth-child(2){margin:0 25px;width:150px}.pmbl-item:nth-child(3){width:70px}div.pmb-list select{border:0}div.pmb-list .pml-item:not(:last-child){padding:0 5px}.modal-create-bucket .modal-dialog{position:fixed;right:25px;bottom:95px;margin:0;height:110px}.modal-create-bucket .modal-content{width:100%;height:100%}',""]); +"use strict";function t(A,M){if("string"!=typeof A)throw new TypeError("argument str must be a string");for(var t={},I=M||{},i=A.split(T),E=I.decode||e,N=0;Nli{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\\F000"}.fa-music:before{content:"\\F001"}.fa-search:before{content:"\\F002"}.fa-envelope-o:before{content:"\\F003"}.fa-heart:before{content:"\\F004"}.fa-star:before{content:"\\F005"}.fa-star-o:before{content:"\\F006"}.fa-user:before{content:"\\F007"}.fa-film:before{content:"\\F008"}.fa-th-large:before{content:"\\F009"}.fa-th:before{content:"\\F00A"}.fa-th-list:before{content:"\\F00B"}.fa-check:before{content:"\\F00C"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\\F00D"}.fa-search-plus:before{content:"\\F00E"}.fa-search-minus:before{content:"\\F010"}.fa-power-off:before{content:"\\F011"}.fa-signal:before{content:"\\F012"}.fa-cog:before,.fa-gear:before{content:"\\F013"}.fa-trash-o:before{content:"\\F014"}.fa-home:before{content:"\\F015"}.fa-file-o:before{content:"\\F016"}.fa-clock-o:before{content:"\\F017"}.fa-road:before{content:"\\F018"}.fa-download:before{content:"\\F019"}.fa-arrow-circle-o-down:before{content:"\\F01A"}.fa-arrow-circle-o-up:before{content:"\\F01B"}.fa-inbox:before{content:"\\F01C"}.fa-play-circle-o:before{content:"\\F01D"}.fa-repeat:before,.fa-rotate-right:before{content:"\\F01E"}.fa-refresh:before{content:"\\F021"}.fa-list-alt:before{content:"\\F022"}.fa-lock:before{content:"\\F023"}.fa-flag:before{content:"\\F024"}.fa-headphones:before{content:"\\F025"}.fa-volume-off:before{content:"\\F026"}.fa-volume-down:before{content:"\\F027"}.fa-volume-up:before{content:"\\F028"}.fa-qrcode:before{content:"\\F029"}.fa-barcode:before{content:"\\F02A"}.fa-tag:before{content:"\\F02B"}.fa-tags:before{content:"\\F02C"}.fa-book:before{content:"\\F02D"}.fa-bookmark:before{content:"\\F02E"}.fa-print:before{content:"\\F02F"}.fa-camera:before{content:"\\F030"}.fa-font:before{content:"\\F031"}.fa-bold:before{content:"\\F032"}.fa-italic:before{content:"\\F033"}.fa-text-height:before{content:"\\F034"}.fa-text-width:before{content:"\\F035"}.fa-align-left:before{content:"\\F036"}.fa-align-center:before{content:"\\F037"}.fa-align-right:before{content:"\\F038"}.fa-align-justify:before{content:"\\F039"}.fa-list:before{content:"\\F03A"}.fa-dedent:before,.fa-outdent:before{content:"\\F03B"}.fa-indent:before{content:"\\F03C"}.fa-video-camera:before{content:"\\F03D"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\\F03E"}.fa-pencil:before{content:"\\F040"}.fa-map-marker:before{content:"\\F041"}.fa-adjust:before{content:"\\F042"}.fa-tint:before{content:"\\F043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\\F044"}.fa-share-square-o:before{content:"\\F045"}.fa-check-square-o:before{content:"\\F046"}.fa-arrows:before{content:"\\F047"}.fa-step-backward:before{content:"\\F048"}.fa-fast-backward:before{content:"\\F049"}.fa-backward:before{content:"\\F04A"}.fa-play:before{content:"\\F04B"}.fa-pause:before{content:"\\F04C"}.fa-stop:before{content:"\\F04D"}.fa-forward:before{content:"\\F04E"}.fa-fast-forward:before{content:"\\F050"}.fa-step-forward:before{content:"\\F051"}.fa-eject:before{content:"\\F052"}.fa-chevron-left:before{content:"\\F053"}.fa-chevron-right:before{content:"\\F054"}.fa-plus-circle:before{content:"\\F055"}.fa-minus-circle:before{content:"\\F056"}.fa-times-circle:before{content:"\\F057"}.fa-check-circle:before{content:"\\F058"}.fa-question-circle:before{content:"\\F059"}.fa-info-circle:before{content:"\\F05A"}.fa-crosshairs:before{content:"\\F05B"}.fa-times-circle-o:before{content:"\\F05C"}.fa-check-circle-o:before{content:"\\F05D"}.fa-ban:before{content:"\\F05E"}.fa-arrow-left:before{content:"\\F060"}.fa-arrow-right:before{content:"\\F061"}.fa-arrow-up:before{content:"\\F062"}.fa-arrow-down:before{content:"\\F063"}.fa-mail-forward:before,.fa-share:before{content:"\\F064"}.fa-expand:before{content:"\\F065"}.fa-compress:before{content:"\\F066"}.fa-plus:before{content:"\\F067"}.fa-minus:before{content:"\\F068"}.fa-asterisk:before{content:"\\F069"}.fa-exclamation-circle:before{content:"\\F06A"}.fa-gift:before{content:"\\F06B"}.fa-leaf:before{content:"\\F06C"}.fa-fire:before{content:"\\F06D"}.fa-eye:before{content:"\\F06E"}.fa-eye-slash:before{content:"\\F070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\\F071"}.fa-plane:before{content:"\\F072"}.fa-calendar:before{content:"\\F073"}.fa-random:before{content:"\\F074"}.fa-comment:before{content:"\\F075"}.fa-magnet:before{content:"\\F076"}.fa-chevron-up:before{content:"\\F077"}.fa-chevron-down:before{content:"\\F078"}.fa-retweet:before{content:"\\F079"}.fa-shopping-cart:before{content:"\\F07A"}.fa-folder:before{content:"\\F07B"}.fa-folder-open:before{content:"\\F07C"}.fa-arrows-v:before{content:"\\F07D"}.fa-arrows-h:before{content:"\\F07E"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\\F080"}.fa-twitter-square:before{content:"\\F081"}.fa-facebook-square:before{content:"\\F082"}.fa-camera-retro:before{content:"\\F083"}.fa-key:before{content:"\\F084"}.fa-cogs:before,.fa-gears:before{content:"\\F085"}.fa-comments:before{content:"\\F086"}.fa-thumbs-o-up:before{content:"\\F087"}.fa-thumbs-o-down:before{content:"\\F088"}.fa-star-half:before{content:"\\F089"}.fa-heart-o:before{content:"\\F08A"}.fa-sign-out:before{content:"\\F08B"}.fa-linkedin-square:before{content:"\\F08C"}.fa-thumb-tack:before{content:"\\F08D"}.fa-external-link:before{content:"\\F08E"}.fa-sign-in:before{content:"\\F090"}.fa-trophy:before{content:"\\F091"}.fa-github-square:before{content:"\\F092"}.fa-upload:before{content:"\\F093"}.fa-lemon-o:before{content:"\\F094"}.fa-phone:before{content:"\\F095"}.fa-square-o:before{content:"\\F096"}.fa-bookmark-o:before{content:"\\F097"}.fa-phone-square:before{content:"\\F098"}.fa-twitter:before{content:"\\F099"}.fa-facebook-f:before,.fa-facebook:before{content:"\\F09A"}.fa-github:before{content:"\\F09B"}.fa-unlock:before{content:"\\F09C"}.fa-credit-card:before{content:"\\F09D"}.fa-feed:before,.fa-rss:before{content:"\\F09E"}.fa-hdd-o:before{content:"\\F0A0"}.fa-bullhorn:before{content:"\\F0A1"}.fa-bell:before{content:"\\F0F3"}.fa-certificate:before{content:"\\F0A3"}.fa-hand-o-right:before{content:"\\F0A4"}.fa-hand-o-left:before{content:"\\F0A5"}.fa-hand-o-up:before{content:"\\F0A6"}.fa-hand-o-down:before{content:"\\F0A7"}.fa-arrow-circle-left:before{content:"\\F0A8"}.fa-arrow-circle-right:before{content:"\\F0A9"}.fa-arrow-circle-up:before{content:"\\F0AA"}.fa-arrow-circle-down:before{content:"\\F0AB"}.fa-globe:before{content:"\\F0AC"}.fa-wrench:before{content:"\\F0AD"}.fa-tasks:before{content:"\\F0AE"}.fa-filter:before{content:"\\F0B0"}.fa-briefcase:before{content:"\\F0B1"}.fa-arrows-alt:before{content:"\\F0B2"}.fa-group:before,.fa-users:before{content:"\\F0C0"}.fa-chain:before,.fa-link:before{content:"\\F0C1"}.fa-cloud:before{content:"\\F0C2"}.fa-flask:before{content:"\\F0C3"}.fa-cut:before,.fa-scissors:before{content:"\\F0C4"}.fa-copy:before,.fa-files-o:before{content:"\\F0C5"}.fa-paperclip:before{content:"\\F0C6"}.fa-floppy-o:before,.fa-save:before{content:"\\F0C7"}.fa-square:before{content:"\\F0C8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\\F0C9"}.fa-list-ul:before{content:"\\F0CA"}.fa-list-ol:before{content:"\\F0CB"}.fa-strikethrough:before{content:"\\F0CC"}.fa-underline:before{content:"\\F0CD"}.fa-table:before{content:"\\F0CE"}.fa-magic:before{content:"\\F0D0"}.fa-truck:before{content:"\\F0D1"}.fa-pinterest:before{content:"\\F0D2"}.fa-pinterest-square:before{content:"\\F0D3"}.fa-google-plus-square:before{content:"\\F0D4"}.fa-google-plus:before{content:"\\F0D5"}.fa-money:before{content:"\\F0D6"}.fa-caret-down:before{content:"\\F0D7"}.fa-caret-up:before{content:"\\F0D8"}.fa-caret-left:before{content:"\\F0D9"}.fa-caret-right:before{content:"\\F0DA"}.fa-columns:before{content:"\\F0DB"}.fa-sort:before,.fa-unsorted:before{content:"\\F0DC"}.fa-sort-desc:before,.fa-sort-down:before{content:"\\F0DD"}.fa-sort-asc:before,.fa-sort-up:before{content:"\\F0DE"}.fa-envelope:before{content:"\\F0E0"}.fa-linkedin:before{content:"\\F0E1"}.fa-rotate-left:before,.fa-undo:before{content:"\\F0E2"}.fa-gavel:before,.fa-legal:before{content:"\\F0E3"}.fa-dashboard:before,.fa-tachometer:before{content:"\\F0E4"}.fa-comment-o:before{content:"\\F0E5"}.fa-comments-o:before{content:"\\F0E6"}.fa-bolt:before,.fa-flash:before{content:"\\F0E7"}.fa-sitemap:before{content:"\\F0E8"}.fa-umbrella:before{content:"\\F0E9"}.fa-clipboard:before,.fa-paste:before{content:"\\F0EA"}.fa-lightbulb-o:before{content:"\\F0EB"}.fa-exchange:before{content:"\\F0EC"}.fa-cloud-download:before{content:"\\F0ED"}.fa-cloud-upload:before{content:"\\F0EE"}.fa-user-md:before{content:"\\F0F0"}.fa-stethoscope:before{content:"\\F0F1"}.fa-suitcase:before{content:"\\F0F2"}.fa-bell-o:before{content:"\\F0A2"}.fa-coffee:before{content:"\\F0F4"}.fa-cutlery:before{content:"\\F0F5"}.fa-file-text-o:before{content:"\\F0F6"}.fa-building-o:before{content:"\\F0F7"}.fa-hospital-o:before{content:"\\F0F8"}.fa-ambulance:before{content:"\\F0F9"}.fa-medkit:before{content:"\\F0FA"}.fa-fighter-jet:before{content:"\\F0FB"}.fa-beer:before{content:"\\F0FC"}.fa-h-square:before{content:"\\F0FD"}.fa-plus-square:before{content:"\\F0FE"}.fa-angle-double-left:before{content:"\\F100"}.fa-angle-double-right:before{content:"\\F101"}.fa-angle-double-up:before{content:"\\F102"}.fa-angle-double-down:before{content:"\\F103"}.fa-angle-left:before{content:"\\F104"}.fa-angle-right:before{content:"\\F105"}.fa-angle-up:before{content:"\\F106"}.fa-angle-down:before{content:"\\F107"}.fa-desktop:before{content:"\\F108"}.fa-laptop:before{content:"\\F109"}.fa-tablet:before{content:"\\F10A"}.fa-mobile-phone:before,.fa-mobile:before{content:"\\F10B"}.fa-circle-o:before{content:"\\F10C"}.fa-quote-left:before{content:"\\F10D"}.fa-quote-right:before{content:"\\F10E"}.fa-spinner:before{content:"\\F110"}.fa-circle:before{content:"\\F111"}.fa-mail-reply:before,.fa-reply:before{content:"\\F112"}.fa-github-alt:before{content:"\\F113"}.fa-folder-o:before{content:"\\F114"}.fa-folder-open-o:before{content:"\\F115"}.fa-smile-o:before{content:"\\F118"}.fa-frown-o:before{content:"\\F119"}.fa-meh-o:before{content:"\\F11A"}.fa-gamepad:before{content:"\\F11B"}.fa-keyboard-o:before{content:"\\F11C"}.fa-flag-o:before{content:"\\F11D"}.fa-flag-checkered:before{content:"\\F11E"}.fa-terminal:before{content:"\\F120"}.fa-code:before{content:"\\F121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\\F122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\\F123"}.fa-location-arrow:before{content:"\\F124"}.fa-crop:before{content:"\\F125"}.fa-code-fork:before{content:"\\F126"}.fa-chain-broken:before,.fa-unlink:before{content:"\\F127"}.fa-question:before{content:"\\F128"}.fa-info:before{content:"\\F129"}.fa-exclamation:before{content:"\\F12A"}.fa-superscript:before{content:"\\F12B"}.fa-subscript:before{content:"\\F12C"}.fa-eraser:before{content:"\\F12D"}.fa-puzzle-piece:before{content:"\\F12E"}.fa-microphone:before{content:"\\F130"}.fa-microphone-slash:before{content:"\\F131"}.fa-shield:before{content:"\\F132"}.fa-calendar-o:before{content:"\\F133"}.fa-fire-extinguisher:before{content:"\\F134"}.fa-rocket:before{content:"\\F135"}.fa-maxcdn:before{content:"\\F136"}.fa-chevron-circle-left:before{content:"\\F137"}.fa-chevron-circle-right:before{content:"\\F138"}.fa-chevron-circle-up:before{content:"\\F139"}.fa-chevron-circle-down:before{content:"\\F13A"}.fa-html5:before{content:"\\F13B"}.fa-css3:before{content:"\\F13C"}.fa-anchor:before{content:"\\F13D"}.fa-unlock-alt:before{content:"\\F13E"}.fa-bullseye:before{content:"\\F140"}.fa-ellipsis-h:before{content:"\\F141"}.fa-ellipsis-v:before{content:"\\F142"}.fa-rss-square:before{content:"\\F143"}.fa-play-circle:before{content:"\\F144"}.fa-ticket:before{content:"\\F145"}.fa-minus-square:before{content:"\\F146"}.fa-minus-square-o:before{content:"\\F147"}.fa-level-up:before{content:"\\F148"}.fa-level-down:before{content:"\\F149"}.fa-check-square:before{content:"\\F14A"}.fa-pencil-square:before{content:"\\F14B"}.fa-external-link-square:before{content:"\\F14C"}.fa-share-square:before{content:"\\F14D"}.fa-compass:before{content:"\\F14E"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\\F150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\\F151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\\F152"}.fa-eur:before,.fa-euro:before{content:"\\F153"}.fa-gbp:before{content:"\\F154"}.fa-dollar:before,.fa-usd:before{content:"\\F155"}.fa-inr:before,.fa-rupee:before{content:"\\F156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\\F157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\\F158"}.fa-krw:before,.fa-won:before{content:"\\F159"}.fa-bitcoin:before,.fa-btc:before{content:"\\F15A"}.fa-file:before{content:"\\F15B"}.fa-file-text:before{content:"\\F15C"}.fa-sort-alpha-asc:before{content:"\\F15D"}.fa-sort-alpha-desc:before{content:"\\F15E"}.fa-sort-amount-asc:before{content:"\\F160"}.fa-sort-amount-desc:before{content:"\\F161"}.fa-sort-numeric-asc:before{content:"\\F162"}.fa-sort-numeric-desc:before{content:"\\F163"}.fa-thumbs-up:before{content:"\\F164"}.fa-thumbs-down:before{content:"\\F165"}.fa-youtube-square:before{content:"\\F166"}.fa-youtube:before{content:"\\F167"}.fa-xing:before{content:"\\F168"}.fa-xing-square:before{content:"\\F169"}.fa-youtube-play:before{content:"\\F16A"}.fa-dropbox:before{content:"\\F16B"}.fa-stack-overflow:before{content:"\\F16C"}.fa-instagram:before{content:"\\F16D"}.fa-flickr:before{content:"\\F16E"}.fa-adn:before{content:"\\F170"}.fa-bitbucket:before{content:"\\F171"}.fa-bitbucket-square:before{content:"\\F172"}.fa-tumblr:before{content:"\\F173"}.fa-tumblr-square:before{content:"\\F174"}.fa-long-arrow-down:before{content:"\\F175"}.fa-long-arrow-up:before{content:"\\F176"}.fa-long-arrow-left:before{content:"\\F177"}.fa-long-arrow-right:before{content:"\\F178"}.fa-apple:before{content:"\\F179"}.fa-windows:before{content:"\\F17A"}.fa-android:before{content:"\\F17B"}.fa-linux:before{content:"\\F17C"}.fa-dribbble:before{content:"\\F17D"}.fa-skype:before{content:"\\F17E"}.fa-foursquare:before{content:"\\F180"}.fa-trello:before{content:"\\F181"}.fa-female:before{content:"\\F182"}.fa-male:before{content:"\\F183"}.fa-gittip:before,.fa-gratipay:before{content:"\\F184"}.fa-sun-o:before{content:"\\F185"}.fa-moon-o:before{content:"\\F186"}.fa-archive:before{content:"\\F187"}.fa-bug:before{content:"\\F188"}.fa-vk:before{content:"\\F189"}.fa-weibo:before{content:"\\F18A"}.fa-renren:before{content:"\\F18B"}.fa-pagelines:before{content:"\\F18C"}.fa-stack-exchange:before{content:"\\F18D"}.fa-arrow-circle-o-right:before{content:"\\F18E"}.fa-arrow-circle-o-left:before{content:"\\F190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\\F191"}.fa-dot-circle-o:before{content:"\\F192"}.fa-wheelchair:before{content:"\\F193"}.fa-vimeo-square:before{content:"\\F194"}.fa-try:before,.fa-turkish-lira:before{content:"\\F195"}.fa-plus-square-o:before{content:"\\F196"}.fa-space-shuttle:before{content:"\\F197"}.fa-slack:before{content:"\\F198"}.fa-envelope-square:before{content:"\\F199"}.fa-wordpress:before{content:"\\F19A"}.fa-openid:before{content:"\\F19B"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\\F19C"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\\F19D"}.fa-yahoo:before{content:"\\F19E"}.fa-google:before{content:"\\F1A0"}.fa-reddit:before{content:"\\F1A1"}.fa-reddit-square:before{content:"\\F1A2"}.fa-stumbleupon-circle:before{content:"\\F1A3"}.fa-stumbleupon:before{content:"\\F1A4"}.fa-delicious:before{content:"\\F1A5"}.fa-digg:before{content:"\\F1A6"}.fa-pied-piper-pp:before{content:"\\F1A7"}.fa-pied-piper-alt:before{content:"\\F1A8"}.fa-drupal:before{content:"\\F1A9"}.fa-joomla:before{content:"\\F1AA"}.fa-language:before{content:"\\F1AB"}.fa-fax:before{content:"\\F1AC"}.fa-building:before{content:"\\F1AD"}.fa-child:before{content:"\\F1AE"}.fa-paw:before{content:"\\F1B0"}.fa-spoon:before{content:"\\F1B1"}.fa-cube:before{content:"\\F1B2"}.fa-cubes:before{content:"\\F1B3"}.fa-behance:before{content:"\\F1B4"}.fa-behance-square:before{content:"\\F1B5"}.fa-steam:before{content:"\\F1B6"}.fa-steam-square:before{content:"\\F1B7"}.fa-recycle:before{content:"\\F1B8"}.fa-automobile:before,.fa-car:before{content:"\\F1B9"}.fa-cab:before,.fa-taxi:before{content:"\\F1BA"}.fa-tree:before{content:"\\F1BB"}.fa-spotify:before{content:"\\F1BC"}.fa-deviantart:before{content:"\\F1BD"}.fa-soundcloud:before{content:"\\F1BE"}.fa-database:before{content:"\\F1C0"}.fa-file-pdf-o:before{content:"\\F1C1"}.fa-file-word-o:before{content:"\\F1C2"}.fa-file-excel-o:before{content:"\\F1C3"}.fa-file-powerpoint-o:before{content:"\\F1C4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\\F1C5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\\F1C6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\\F1C7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\\F1C8"}.fa-file-code-o:before{content:"\\F1C9"}.fa-vine:before{content:"\\F1CA"}.fa-codepen:before{content:"\\F1CB"}.fa-jsfiddle:before{content:"\\F1CC"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\\F1CD"}.fa-circle-o-notch:before{content:"\\F1CE"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\\F1D0"}.fa-empire:before,.fa-ge:before{content:"\\F1D1"}.fa-git-square:before{content:"\\F1D2"}.fa-git:before{content:"\\F1D3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\\F1D4"}.fa-tencent-weibo:before{content:"\\F1D5"}.fa-qq:before{content:"\\F1D6"}.fa-wechat:before,.fa-weixin:before{content:"\\F1D7"}.fa-paper-plane:before,.fa-send:before{content:"\\F1D8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\\F1D9"}.fa-history:before{content:"\\F1DA"}.fa-circle-thin:before{content:"\\F1DB"}.fa-header:before{content:"\\F1DC"}.fa-paragraph:before{content:"\\F1DD"}.fa-sliders:before{content:"\\F1DE"}.fa-share-alt:before{content:"\\F1E0"}.fa-share-alt-square:before{content:"\\F1E1"}.fa-bomb:before{content:"\\F1E2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\\F1E3"}.fa-tty:before{content:"\\F1E4"}.fa-binoculars:before{content:"\\F1E5"}.fa-plug:before{content:"\\F1E6"}.fa-slideshare:before{content:"\\F1E7"}.fa-twitch:before{content:"\\F1E8"}.fa-yelp:before{content:"\\F1E9"}.fa-newspaper-o:before{content:"\\F1EA"}.fa-wifi:before{content:"\\F1EB"}.fa-calculator:before{content:"\\F1EC"}.fa-paypal:before{content:"\\F1ED"}.fa-google-wallet:before{content:"\\F1EE"}.fa-cc-visa:before{content:"\\F1F0"}.fa-cc-mastercard:before{content:"\\F1F1"}.fa-cc-discover:before{content:"\\F1F2"}.fa-cc-amex:before{content:"\\F1F3"}.fa-cc-paypal:before{content:"\\F1F4"}.fa-cc-stripe:before{content:"\\F1F5"}.fa-bell-slash:before{content:"\\F1F6"}.fa-bell-slash-o:before{content:"\\F1F7"}.fa-trash:before{content:"\\F1F8"}.fa-copyright:before{content:"\\F1F9"}.fa-at:before{content:"\\F1FA"}.fa-eyedropper:before{content:"\\F1FB"}.fa-paint-brush:before{content:"\\F1FC"}.fa-birthday-cake:before{content:"\\F1FD"}.fa-area-chart:before{content:"\\F1FE"}.fa-pie-chart:before{content:"\\F200"}.fa-line-chart:before{content:"\\F201"}.fa-lastfm:before{content:"\\F202"}.fa-lastfm-square:before{content:"\\F203"}.fa-toggle-off:before{content:"\\F204"}.fa-toggle-on:before{content:"\\F205"}.fa-bicycle:before{content:"\\F206"}.fa-bus:before{content:"\\F207"}.fa-ioxhost:before{content:"\\F208"}.fa-angellist:before{content:"\\F209"}.fa-cc:before{content:"\\F20A"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\\F20B"}.fa-meanpath:before{content:"\\F20C"}.fa-buysellads:before{content:"\\F20D"}.fa-connectdevelop:before{content:"\\F20E"}.fa-dashcube:before{content:"\\F210"}.fa-forumbee:before{content:"\\F211"}.fa-leanpub:before{content:"\\F212"}.fa-sellsy:before{content:"\\F213"}.fa-shirtsinbulk:before{content:"\\F214"}.fa-simplybuilt:before{content:"\\F215"}.fa-skyatlas:before{content:"\\F216"}.fa-cart-plus:before{content:"\\F217"}.fa-cart-arrow-down:before{content:"\\F218"}.fa-diamond:before{content:"\\F219"}.fa-ship:before{content:"\\F21A"}.fa-user-secret:before{content:"\\F21B"}.fa-motorcycle:before{content:"\\F21C"}.fa-street-view:before{content:"\\F21D"}.fa-heartbeat:before{content:"\\F21E"}.fa-venus:before{content:"\\F221"}.fa-mars:before{content:"\\F222"}.fa-mercury:before{content:"\\F223"}.fa-intersex:before,.fa-transgender:before{content:"\\F224"}.fa-transgender-alt:before{content:"\\F225"}.fa-venus-double:before{content:"\\F226"}.fa-mars-double:before{content:"\\F227"}.fa-venus-mars:before{content:"\\F228"}.fa-mars-stroke:before{content:"\\F229"}.fa-mars-stroke-v:before{content:"\\F22A"}.fa-mars-stroke-h:before{content:"\\F22B"}.fa-neuter:before{content:"\\F22C"}.fa-genderless:before{content:"\\F22D"}.fa-facebook-official:before{content:"\\F230"}.fa-pinterest-p:before{content:"\\F231"}.fa-whatsapp:before{content:"\\F232"}.fa-server:before{content:"\\F233"}.fa-user-plus:before{content:"\\F234"}.fa-user-times:before{content:"\\F235"}.fa-bed:before,.fa-hotel:before{content:"\\F236"}.fa-viacoin:before{content:"\\F237"}.fa-train:before{content:"\\F238"}.fa-subway:before{content:"\\F239"}.fa-medium:before{content:"\\F23A"}.fa-y-combinator:before,.fa-yc:before{content:"\\F23B"}.fa-optin-monster:before{content:"\\F23C"}.fa-opencart:before{content:"\\F23D"}.fa-expeditedssl:before{content:"\\F23E"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\\F240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\\F241"}.fa-battery-2:before,.fa-battery-half:before{content:"\\F242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\\F243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\\F244"}.fa-mouse-pointer:before{content:"\\F245"}.fa-i-cursor:before{content:"\\F246"}.fa-object-group:before{content:"\\F247"}.fa-object-ungroup:before{content:"\\F248"}.fa-sticky-note:before{content:"\\F249"}.fa-sticky-note-o:before{content:"\\F24A"}.fa-cc-jcb:before{content:"\\F24B"}.fa-cc-diners-club:before{content:"\\F24C"}.fa-clone:before{content:"\\F24D"}.fa-balance-scale:before{content:"\\F24E"}.fa-hourglass-o:before{content:"\\F250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\\F251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\\F252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\\F253"}.fa-hourglass:before{content:"\\F254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\\F255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\\F256"}.fa-hand-scissors-o:before{content:"\\F257"}.fa-hand-lizard-o:before{content:"\\F258"}.fa-hand-spock-o:before{content:"\\F259"}.fa-hand-pointer-o:before{content:"\\F25A"}.fa-hand-peace-o:before{content:"\\F25B"}.fa-trademark:before{content:"\\F25C"}.fa-registered:before{content:"\\F25D"}.fa-creative-commons:before{content:"\\F25E"}.fa-gg:before{content:"\\F260"}.fa-gg-circle:before{content:"\\F261"}.fa-tripadvisor:before{content:"\\F262"}.fa-odnoklassniki:before{content:"\\F263"}.fa-odnoklassniki-square:before{content:"\\F264"}.fa-get-pocket:before{content:"\\F265"}.fa-wikipedia-w:before{content:"\\F266"}.fa-safari:before{content:"\\F267"}.fa-chrome:before{content:"\\F268"}.fa-firefox:before{content:"\\F269"}.fa-opera:before{content:"\\F26A"}.fa-internet-explorer:before{content:"\\F26B"}.fa-television:before,.fa-tv:before{content:"\\F26C"}.fa-contao:before{content:"\\F26D"}.fa-500px:before{content:"\\F26E"}.fa-amazon:before{content:"\\F270"}.fa-calendar-plus-o:before{content:"\\F271"}.fa-calendar-minus-o:before{content:"\\F272"}.fa-calendar-times-o:before{content:"\\F273"}.fa-calendar-check-o:before{content:"\\F274"}.fa-industry:before{content:"\\F275"}.fa-map-pin:before{content:"\\F276"}.fa-map-signs:before{content:"\\F277"}.fa-map-o:before{content:"\\F278"}.fa-map:before{content:"\\F279"}.fa-commenting:before{content:"\\F27A"}.fa-commenting-o:before{content:"\\F27B"}.fa-houzz:before{content:"\\F27C"}.fa-vimeo:before{content:"\\F27D"}.fa-black-tie:before{content:"\\F27E"}.fa-fonticons:before{content:"\\F280"}.fa-reddit-alien:before{content:"\\F281"}.fa-edge:before{content:"\\F282"}.fa-credit-card-alt:before{content:"\\F283"}.fa-codiepie:before{content:"\\F284"}.fa-modx:before{content:"\\F285"}.fa-fort-awesome:before{content:"\\F286"}.fa-usb:before{content:"\\F287"}.fa-product-hunt:before{content:"\\F288"}.fa-mixcloud:before{content:"\\F289"}.fa-scribd:before{content:"\\F28A"}.fa-pause-circle:before{content:"\\F28B"}.fa-pause-circle-o:before{content:"\\F28C"}.fa-stop-circle:before{content:"\\F28D"}.fa-stop-circle-o:before{content:"\\F28E"}.fa-shopping-bag:before{content:"\\F290"}.fa-shopping-basket:before{content:"\\F291"}.fa-hashtag:before{content:"\\F292"}.fa-bluetooth:before{content:"\\F293"}.fa-bluetooth-b:before{content:"\\F294"}.fa-percent:before{content:"\\F295"}.fa-gitlab:before{content:"\\F296"}.fa-wpbeginner:before{content:"\\F297"}.fa-wpforms:before{content:"\\F298"}.fa-envira:before{content:"\\F299"}.fa-universal-access:before{content:"\\F29A"}.fa-wheelchair-alt:before{content:"\\F29B"}.fa-question-circle-o:before{content:"\\F29C"}.fa-blind:before{content:"\\F29D"}.fa-audio-description:before{content:"\\F29E"}.fa-volume-control-phone:before{content:"\\F2A0"}.fa-braille:before{content:"\\F2A1"}.fa-assistive-listening-systems:before{content:"\\F2A2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\\F2A3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\\F2A4"}.fa-glide:before{content:"\\F2A5"}.fa-glide-g:before{content:"\\F2A6"}.fa-sign-language:before,.fa-signing:before{content:"\\F2A7"}.fa-low-vision:before{content:"\\F2A8"}.fa-viadeo:before{content:"\\F2A9"}.fa-viadeo-square:before{content:"\\F2AA"}.fa-snapchat:before{content:"\\F2AB"}.fa-snapchat-ghost:before{content:"\\F2AC"}.fa-snapchat-square:before{content:"\\F2AD"}.fa-pied-piper:before{content:"\\F2AE"}.fa-first-order:before{content:"\\F2B0"}.fa-yoast:before{content:"\\F2B1"}.fa-themeisle:before{content:"\\F2B2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\\F2B3"}.fa-fa:before,.fa-font-awesome:before{content:"\\F2B4"}.fa-handshake-o:before{content:"\\F2B5"}.fa-envelope-open:before{content:"\\F2B6"}.fa-envelope-open-o:before{content:"\\F2B7"}.fa-linode:before{content:"\\F2B8"}.fa-address-book:before{content:"\\F2B9"}.fa-address-book-o:before{content:"\\F2BA"}.fa-address-card:before,.fa-vcard:before{content:"\\F2BB"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\\F2BC"}.fa-user-circle:before{content:"\\F2BD"}.fa-user-circle-o:before{content:"\\F2BE"}.fa-user-o:before{content:"\\F2C0"}.fa-id-badge:before{content:"\\F2C1"}.fa-drivers-license:before,.fa-id-card:before{content:"\\F2C2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\\F2C3"}.fa-quora:before{content:"\\F2C4"}.fa-free-code-camp:before{content:"\\F2C5"}.fa-telegram:before{content:"\\F2C6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\\F2C7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\\F2C8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\\F2C9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\\F2CA"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\\F2CB"}.fa-shower:before{content:"\\F2CC"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\\F2CD"}.fa-podcast:before{content:"\\F2CE"}.fa-window-maximize:before{content:"\\F2D0"}.fa-window-minimize:before{content:"\\F2D1"}.fa-window-restore:before{content:"\\F2D2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\\F2D3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\\F2D4"}.fa-bandcamp:before{content:"\\F2D5"}.fa-grav:before{content:"\\F2D6"}.fa-etsy:before{content:"\\F2D7"}.fa-imdb:before{content:"\\F2D8"}.fa-ravelry:before{content:"\\F2D9"}.fa-eercast:before{content:"\\F2DA"}.fa-microchip:before{content:"\\F2DB"}.fa-snowflake-o:before{content:"\\F2DC"}.fa-superpowers:before{content:"\\F2DD"}.fa-wpexplorer:before{content:"\\F2DE"}.fa-meetup:before{content:"\\F2E0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}',""]); +},function(A,M,t){M=A.exports=t(138)(),M.push([A.id,'*,:after,:before{box-sizing:border-box}body{font-family:Lato,sans-serif;font-size:15px;line-height:1.42857143;color:#8e8e8e;background-color:#edecec}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#46a5e0}a,a:focus,a:hover{text-decoration:none}a:focus,a:hover{color:#1f7fba}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#edecec;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:15px;text-align:left;background-color:#fff;border:1px solid transparent;border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:rgba(0,0,0,.08)}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#8e8e8e;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#333;background-color:rgba(0,0,0,.05)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#333;text-decoration:none;outline:0;background-color:rgba(0,0,0,.075)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#e4e4e4}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:13px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid\\9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu>li>a{text-align:right}.navbar-right .dropdown-menu-left{left:0;right:auto}}.modal,.modal-open{overflow:hidden}.modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translateY(-25%);transform:translateY(-25%);-webkit-transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0);transform:translate(0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid transparent;border-radius:6px;box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:rgba(0,0,0,.1)}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:30px 35px 0;border-bottom:1px solid transparent}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:transparent}.modal-body{position:relative;padding:30px 35px}.modal-footer{padding:30px 35px;text-align:right;border-top:1px solid transparent}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:400px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:Lato,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:13px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px}.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow{bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{left:5px}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}*{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}:active,:focus{outline:0}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body,html{min-height:100%}a{-webkit-transition:color;transition:color;-webkit-transition-duration:.3s;transition-duration:.3s}button{border:0}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translateY(-20px)}to{opacity:1;-webkit-transform:translateY(0)}}@keyframes fadeInDown{0%{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translateY(20px)}to{opacity:1;-webkit-transform:translateY(0)}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeOut{0%{opacity:1}to{opacity:0}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1;-webkit-transform:translateY(0)}to{opacity:0;-webkit-transform:translateY(20px)}}@keyframes fadeOutDown{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(20px)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutUp{0%{opacity:1;-webkit-transform:translateY(0)}to{opacity:0;-webkit-transform:translateY(-20px)}}@keyframes fadeOutUp{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-20px)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.text-center{text-align:center!important}.text-left{text-align:left!important}.text-right{text-align:right!important}.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.row:after,.row:before{content:" ";display:table}.clearfix:after,.container-fluid:after,.container:after,.modal-footer:after,.modal-header:after,.row:after{clear:both}.pull-right{float:right!important}.pull-left{float:left!important}.p-relative{position:relative}.m-0{margin:0!important}.m-t-0{margin-top:0!important}.m-b-0{margin-bottom:0!important}.m-l-0{margin-left:0!important}.m-r-0{margin-right:0!important}.m-5{margin:5px!important}.m-t-5{margin-top:5px!important}.m-b-5{margin-bottom:5px!important}.m-l-5{margin-left:5px!important}.m-r-5{margin-right:5px!important}.m-10{margin:10px!important}.m-t-10{margin-top:10px!important}.m-b-10{margin-bottom:10px!important}.m-l-10{margin-left:10px!important}.m-r-10{margin-right:10px!important}.m-15{margin:15px!important}.m-t-15{margin-top:15px!important}.m-b-15{margin-bottom:15px!important}.m-l-15{margin-left:15px!important}.m-r-15{margin-right:15px!important}.m-20{margin:20px!important}.m-t-20{margin-top:20px!important}.m-b-20{margin-bottom:20px!important}.m-l-20{margin-left:20px!important}.m-r-20{margin-right:20px!important}.m-25{margin:25px!important}.m-t-25{margin-top:25px!important}.m-b-25{margin-bottom:25px!important}.m-l-25{margin-left:25px!important}.m-r-25{margin-right:25px!important}.m-30{margin:30px!important}.m-t-30{margin-top:30px!important}.m-b-30{margin-bottom:30px!important}.m-l-30{margin-left:30px!important}.m-r-30{margin-right:30px!important}.p-0{padding:0!important}.p-t-0{padding-top:0!important}.p-b-0{padding-bottom:0!important}.p-l-0{padding-left:0!important}.p-r-0{padding-right:0!important}.p-5{padding:5px!important}.p-t-5{padding-top:5px!important}.p-b-5{padding-bottom:5px!important}.p-l-5{padding-left:5px!important}.p-r-5{padding-right:5px!important}.p-10{padding:10px!important}.p-t-10{padding-top:10px!important}.p-b-10{padding-bottom:10px!important}.p-l-10{padding-left:10px!important}.p-r-10{padding-right:10px!important}.p-15{padding:15px!important}.p-t-15{padding-top:15px!important}.p-b-15{padding-bottom:15px!important}.p-l-15{padding-left:15px!important}.p-r-15{padding-right:15px!important}.p-20{padding:20px!important}.p-t-20{padding-top:20px!important}.p-b-20{padding-bottom:20px!important}.p-l-20{padding-left:20px!important}.p-r-20{padding-right:20px!important}.p-25{padding:25px!important}.p-t-25{padding-top:25px!important}.p-b-25{padding-bottom:25px!important}.p-l-25{padding-left:25px!important}.p-r-25{padding-right:25px!important}.p-30{padding:30px!important}.p-t-30{padding-top:30px!important}.p-b-30{padding-bottom:30px!important}.p-l-30{padding-left:30px!important}.p-r-30{padding-right:30px!important}@font-face{font-family:Lato;src:url('+t(515)+') format("woff2"),url('+t(514)+') format("woff");font-weight:400;font-style:normal}.form-control{border:0;border-bottom:1px solid #eee;color:#32393f;padding:5px;width:100%;font-size:13px;background-color:transparent}select.form-control{-webkit-appearance:none;-moz-appearance:none;border-radius:0;background:url('+t(518)+') no-repeat bottom 7px right}.input-group{position:relative}.input-group:not(:last-child){margin-bottom:25px}.input-group label:not(.ig-label){font-size:13px;display:block;margin-bottom:10px}.ig-label{position:absolute;text-align:center;bottom:7px;left:0;width:100%;-webkit-transition:all;transition:all;-webkit-transition-duration:.25s;transition-duration:.25s;padding:2px 0 3px;border-radius:2px;font-weight:400}.ig-helpers{z-index:1;width:100%;left:0}.ig-helpers,.ig-helpers:after,.ig-helpers:before{position:absolute;height:2px;bottom:0}.ig-helpers:after,.ig-helpers:before{content:"";width:0;-webkit-transition:all;transition:all;-webkit-transition-duration:.25s;transition-duration:.25s;background-color:#03a9f4}.ig-helpers:before{left:50%}.ig-helpers:after{right:50%}.ig-text{width:100%;height:40px;border:0;background:transparent;text-align:center;position:relative;z-index:1;border-bottom:1px solid #eee;color:#32393f;font-size:13px}.ig-text:focus+.ig-helpers:after,.ig-text:focus+.ig-helpers:before{width:50%}.ig-text:disabled~.ig-label,.ig-text:focus~.ig-label,.ig-text:valid~.ig-label{bottom:35px;font-size:13px;z-index:1}.ig-text:disabled{opacity:.5;filter:alpha(opacity=50)}.ig-dark .ig-text{color:#fff;border-color:hsla(0,0%,100%,.1)}.ig-dark .ig-helpers:after,.ig-dark .ig-helpers:before{background-color:#dfdfdf;height:1px}.ig-left .ig-label,.ig-left .ig-text{text-align:left}.ig-error .ig-label{color:#e23f3f}.ig-error .ig-helpers i:first-child,.ig-error .ig-helpers i:first-child:after,.ig-error .ig-helpers i:first-child:before{background:rgba(226,63,63,.43)}.ig-error .ig-helpers i:last-child,.ig-error .ig-helpers i:last-child:after,.ig-error .ig-helpers i:last-child:before{background:#e23f3f!important}.ig-error:after{content:"\\F05A";font-family:FontAwesome;position:absolute;top:17px;right:9px;font-size:20px;color:#d33d3e}.ig-search:before{font-family:fontAwesome;content:"\\F002";font-size:15px;position:absolute;left:2px;top:8px}.ig-search .ig-text{padding-left:25px}.set-expire{border:1px solid #eee;margin:35px 0 30px}.set-expire-item{padding:9px 5px 3px;position:relative;display:table-cell;width:1%;text-align:center}.set-expire-item:not(:last-child){border-right:1px solid #eee}.set-expire-title{font-size:10px;text-transform:uppercase}.set-expire-value{display:inline-block;overflow:hidden;position:relative;left:-8px}.set-expire-value input{font-size:20px;text-align:center;position:relative;right:-15px;border:0;color:#333;padding:0;height:25px;width:100%;font-weight:400}.set-expire-decrease,.set-expire-increase{position:absolute;width:20px;height:20px;background:url('+t(516)+') no-repeat 50%;background-size:85%;left:50%;margin-left:-10px;opacity:.2;filter:alpha(opacity=20);cursor:pointer}.set-expire-decrease:hover,.set-expire-increase:hover{opacity:.5;filter:alpha(opacity=50)}.set-expire-increase{top:-25px}.set-expire-decrease{bottom:-27px;-webkit-transform:rotate(-180deg);transform:rotate(-180deg)}.btn{border:0;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:2px;text-align:center;-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}.btn:focus,.btn:hover{opacity:.9;filter:alpha(opacity=90)}.btn-block{display:block;width:100%}.btn-link{color:#545454;background-color:#eee}.btn-link:focus,.btn-link:hover{color:#545454;background-color:#dfdfdf}.btn-danger{color:#fff;background-color:#ff726f}.btn-danger:focus,.btn-danger:hover{color:#fff;background-color:#ff5450}.btn-primary{color:#fff;background-color:#50b2ff}.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#31a5ff}.btn-success{color:#fff;background-color:#33d46f}.btn-success:focus,.btn-success:hover{color:#fff;background-color:#28c061}.close{right:15px;font-weight:400;opacity:1;font-size:18px;position:absolute;text-align:center;top:16px;z-index:1;padding:0;border:0;background-color:transparent}.close span{width:25px;height:25px;display:block;border-radius:50%;line-height:24px;text-shadow:none}.close:not(.close-alt) span{background-color:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.8)}.close:not(.close-alt):focus span,.close:not(.close-alt):hover span{background-color:hsla(0,0%,100%,.2);color:#fff}.close-alt span{background-color:#efefef;color:#989898}.close-alt:focus span,.close-alt:hover span{background-color:#e8e8e8;color:#7b7b7b}.hidden{display:none!important}.copy-text input{width:100%;border-radius:1px;border:1px solid #eee;padding:7px 12px;font-size:13px;line-height:100%;cursor:text;-webkit-transition:border-color;transition:border-color;-webkit-transition-duration:.3s;transition-duration:.3s}.copy-text input:hover{border-color:#e1e1e1}.share-availability{margin-bottom:40px}.share-availability:after,.share-availability:before{position:absolute;bottom:-30px;font-size:10px}.share-availability:before{content:"01 Sec";left:0}.share-availability:after{content:"7 days";right:0}.login{height:100vh;min-height:500px;background:#32393f;text-align:center}.login:before{height:calc(100% - 110px);width:1px;content:""}.l-wrap,.login:before{display:inline-block;vertical-align:middle}.l-wrap{width:80%;max-width:500px;margin-top:-50px}.l-wrap.toggled{display:inline-block}.l-wrap .input-group:not(:last-child){margin-bottom:40px}.l-footer{height:110px;padding:0 50px}.lf-logo{float:right}.lf-logo img{width:40px}.lf-server{float:left;color:hsla(0,0%,100%,.4);font-size:20px;font-weight:400;padding-top:40px}@media (max-width:768px){.lf-logo,.lf-server{float:none;display:block;text-align:center;width:100%}.lf-logo{margin-bottom:5px}.lf-server{font-size:15px}}.lw-btn{width:50px;height:50px;border:1px solid #fff;display:inline-block;border-radius:50%;font-size:22px;color:#fff;-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s;opacity:.3;background-color:transparent;line-height:45px;padding:0}.lw-btn:hover{color:#fff;opacity:.8;border-color:#fff}.lw-btn i{display:block;width:100%;padding-left:3px}input:-webkit-autofill{-webkit-box-shadow:0 0 0 50px #32393f inset!important;-webkit-text-fill-color:#fff!important}.fe-header{padding:45px 55px 20px}@media (min-width:992px){.fe-header{position:relative}}@media (max-width:667px){.fe-header{padding:25px 25px 20px}}.fe-header h2{font-size:16px;font-weight:400;margin:0}.fe-header h2>span{margin-bottom:7px;display:inline-block}.fe-header h2>span:not(:first-child):before{content:"/";margin:0 4px;color:#8e8e8e}.fe-header p{margin-top:7px}.feh-usage{margin-top:12px;max-width:285px}@media (max-width:667px){.feh-usage{max-width:100%;font-size:12px}}.feh-usage>ul{margin-top:7px;list-style:none;padding:0}.feh-usage>ul>li{padding-right:0;display:inline-block}.fehu-chart{height:5px;background:#eee;position:relative;border-radius:2px;overflow:hidden}.fehu-chart>div{position:absolute;left:0;height:100%;background:#46a5e0}.feh-actions{list-style:none;padding:0;margin:0;position:absolute;right:35px;top:30px;z-index:11}@media (max-width:991px){.feh-actions{top:7px;right:10px;position:fixed}}.feh-actions>li{display:inline-block;text-align:right;vertical-align:top;line-height:100%}.feh-actions>li>.btn-group>button,.feh-actions>li>a{display:block;height:45px;min-width:45px;text-align:center;border-radius:50%;padding:0;border:0;background:none}@media (min-width:992px){.feh-actions>li>.btn-group>button,.feh-actions>li>a{color:#7b7b7b;font-size:21px;line-height:45px;-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}.feh-actions>li>.btn-group>button:hover,.feh-actions>li>a:hover{background:rgba(0,0,0,.09)}}@media (max-width:991px){.feh-actions>li>.btn-group>button,.feh-actions>li>a{background:url('+t(237)+') no-repeat 50%}.feh-actions>li>.btn-group>button .fa-reorder,.feh-actions>li>a .fa-reorder{display:none}}@media (max-width:991px){.fe-header-mobile{background-color:#32393f;padding:10px 50px 9px 12px;text-align:center;position:fixed;z-index:10;box-shadow:0 0 10px rgba(0,0,0,.3);left:0;top:0;width:100%}.fe-header-mobile .mh-logo{height:35px;position:relative;top:4px}.feh-trigger{width:41px;height:41px;cursor:pointer;float:left;position:relative;text-align:center}.feh-trigger:after,.feh-trigger:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;border-radius:50%}.feh-trigger:after{z-index:1}.feh-trigger:before{background:hsla(0,0%,100%,.1);-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:scale(0);transform:scale(0)}.feht-toggled:before{-webkit-transform:scale(1);transform:scale(1)}.feht-toggled .feht-lines{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.feht-toggled .feht-lines>div.top{width:12px;transform:translateX(8px) translateY(1px) rotate(45deg);-webkit-transform:translateX(8px) translateY(1px) rotate(45deg)}.feht-toggled .feht-lines>div.bottom{width:12px;transform:translateX(8px) translateY(-1px) rotate(-45deg);-webkit-transform:translateX(8px) translateY(-1px) rotate(-45deg)}.feht-lines,.feht-lines>div{-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}.feht-lines{width:18px;height:12px;display:inline-block;margin-top:14px}.feht-lines>div{background-color:#eaeaea;width:18px;height:2px}.feht-lines>div.center{margin:3px 0}}.fe-sidebar{width:300px;background-color:#32393f;position:fixed;height:100%;overflow:hidden;padding:35px}@media (min-width:992px){.fe-sidebar{-webkit-transform:translateZ(0);transform:translateZ(0)}}@media (max-width:991px){.fe-sidebar{padding-top:85px;z-index:9;box-shadow:0 0 10px rgba(0,0,0,.65);-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:translate3d(-315px,0,0);transform:translate3d(-315px,0,0)}.fe-sidebar.toggled{-webkit-transform:translateZ(0);transform:translateZ(0)}}.fe-sidebar a{color:hsla(0,0%,100%,.58)}.fe-sidebar a:hover{color:#fff}.fes-header{margin-bottom:40px}.fes-header h2,.fes-header img{float:left}.fes-header h2{margin:13px 0 0 10px;font-weight:400}.fes-header img{width:32px}.fesl-inner{height:calc(100vh - 260px);overflow:auto;padding:0;margin:0 -35px}.fesl-inner li{position:relative}.fesl-inner li>a{display:block;padding:10px 40px 12px 65px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fesl-inner li>a:before{font-family:FontAwesome;content:"\\F0A0";font-size:17px;position:absolute;top:10px;left:35px;opacity:.8;filter:alpha(opacity=80)}.fesl-inner li>a.fesli-loading:before{content:"";width:20px;height:20px;border-radius:50%;-webkit-animation-name:zoomIn;animation-name:zoomIn;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;border:2px solid hsla(0,0%,100%,.1);border-bottom-color:hsla(0,0%,100%,.5);position:absolute;z-index:1;-webkit-animation:zoomIn .25s,spin .7s .25s infinite linear;animation:zoomIn .25s,spin .7s .25s infinite linear;left:32px;top:0;bottom:0;margin:auto}.fesl-inner li.active{background-color:rgba(0,0,0,.2)}.fesl-inner li.active>a{color:#fff}.fesl-inner li:not(.active):hover{background-color:rgba(0,0,0,.1)}.fesl-inner li:not(.active):hover>a{color:#fff}.fesl-inner li:hover .fesli-trigger{opacity:.6;filter:alpha(opacity=60)}.fesl-inner li:hover .fesli-trigger:hover{opacity:1;filter:alpha(opacity=100)}.fesl-inner ul{list-style:none;padding:0;margin:0}.fesl-inner:hover .scrollbar-vertical{opacity:1}.fesli-trigger{filter:alpha(opacity=0);-webkit-transition:all;transition:all;-webkit-transition-duration:.2s;transition-duration:.2s;top:0;right:0;width:40px;cursor:pointer;background:url('+t(237)+') no-repeat 0}.fesli-trigger,.scrollbar-vertical{opacity:0;position:absolute;height:100%}.scrollbar-vertical{right:5px;width:4px;-webkit-transition:opacity;transition:opacity;-webkit-transition-duration:.3s;transition-duration:.3s}.scrollbar-vertical div{border-radius:1px!important;background-color:#6a6a6a!important}.fes-host{position:fixed;left:0;bottom:0;z-index:1;background:#32393f;color:hsla(0,0%,100%,.4);font-size:15px;font-weight:400;width:300px;padding:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fes-host>i{margin-right:10px}.fesl-row{padding-right:40px;padding-top:5px;padding-bottom:5px;position:relative}@media (min-width:668px){.fesl-row{display:flex;flex-flow:row nowrap;justify-content:space-between}}.fesl-row:after,.fesl-row:before{content:" ";display:table}.fesl-row:after{clear:both}@media (min-width:668px){header.fesl-row{margin-bottom:20px;border-bottom:1px solid #f0f0f0;padding-left:40px}header.fesl-row .fesl-item,header.fesl-row .fesli-sort{-webkit-transition:all;transition:all;-webkit-transition-duration:.3s;transition-duration:.3s}header.fesl-row .fesl-item{cursor:pointer;color:#8e8e8e;font-weight:500;margin-bottom:-5px}header.fesl-row .fesl-item>.fesli-sort{float:right;margin:4px 0 0;opacity:0;filter:alpha(opacity=0);color:#32393f;font-size:14px}header.fesl-row .fesl-item:hover:not(.fi-actions){background:#f5f5f5;color:#32393f}header.fesl-row .fesl-item:hover:not(.fi-actions)>.fesli-sort{opacity:.5;filter:alpha(opacity=50)}}@media (max-width:667px){header.fesl-row{display:none}}div.fesl-row{padding-left:85px;border-bottom:1px solid transparent;cursor:default}@media (max-width:667px){div.fesl-row{padding-left:70px;padding-right:45px}}div.fesl-row:nth-child(2n){background-color:#fafafa}div.fesl-row:hover{background-color:#fbf7dc}div.fesl-row[data-type]:before{font-family:fontAwesome;width:35px;height:35px;text-align:center;line-height:35px;position:absolute;border-radius:50%;font-size:16px;left:50px;top:9px;color:#fff}@media (max-width:667px){div.fesl-row[data-type]:before{left:20px}}@media (max-width:667px){div.fesl-row[data-type=folder] .fesl-item.fi-name{padding-top:10px;padding-bottom:7px}div.fesl-row[data-type=folder] .fesl-item.fi-modified,div.fesl-row[data-type=folder] .fesl-item.fi-size{display:none}}div.fesl-row[data-type=folder]:before{content:"\\F114";background-color:#a1d6dd}div.fesl-row[data-type=pdf]:before{content:"\\F1C1";background-color:#fa7775}div.fesl-row[data-type=zip]:before{content:"\\F1C6";background-color:#427089}div.fesl-row[data-type=audio]:before{content:"\\F1C7";background-color:#009688}div.fesl-row[data-type=code]:before{content:"\\F1C9";background-color:#997867}div.fesl-row[data-type=excel]:before{content:"\\F1C3";background-color:#64c866}div.fesl-row[data-type=image]:before{content:"\\F1C5";background-color:#f06292}div.fesl-row[data-type=video]:before{content:"\\F1C8";background-color:#f8c363}div.fesl-row[data-type=other]:before{content:"\\F016";background-color:#afafaf}div.fesl-row[data-type=text]:before{content:"\\F0F6";background-color:#8a8a8a}div.fesl-row[data-type=doc]:before{content:"\\F1C2";background-color:#2196f5}div.fesl-row[data-type=presentation]:before{content:"\\F1C4";background-color:#896ea6}div.fesl-row.fesl-loading:before{content:""}div.fesl-row.fesl-loading:after{content:"";width:20px;height:20px;border-radius:50%;-webkit-animation-name:zoomIn;animation-name:zoomIn;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;border:2px solid hsla(0,0%,100%,.5);border-bottom-color:#fff;position:absolute;z-index:1;-webkit-animation:zoomIn .25s,spin .7s .25s infinite linear;animation:zoomIn .25s,spin .7s .25s infinite linear;left:57px;top:17px}@media (max-width:667px){div.fesl-row.fesl-loading:after{left:27px}}.fesl-item{display:block}.fesl-item a{color:#818181}@media (min-width:668px){.fesl-item:not(.fi-actions){text-overflow:ellipsis;padding:10px 15px;white-space:nowrap;overflow:hidden}.fesl-item.fi-name{flex:3}.fesl-item.fi-size{width:140px}.fesl-item.fi-modified{width:190px}.fesl-item.fi-actions{width:40px}}@media (max-width:667px){.fesl-item{padding:0}.fesl-item.fi-name{width:100%;margin-bottom:3px}.fesl-item.fi-modified,.fesl-item.fi-size{font-size:12px;color:#b5b5b5;float:left}.fesl-item.fi-modified{max-width:72px;white-space:nowrap;overflow:hidden}.fesl-item.fi-size{margin-right:10px}.fesl-item.fi-actions{position:absolute;top:5px;right:10px}}.fia-toggle{height:36px;width:36px;background:transparent url('+t(517)+') no-repeat 50%;position:relative;top:3px;opacity:.4;filter:alpha(opacity=40)}.fia-toggle:hover{opacity:.7;filter:alpha(opacity=70)}.fi-actions .dropdown-menu{background-color:transparent;box-shadow:none;padding:0;right:38px;left:auto;margin:0;height:100%;text-align:right}.fi-actions .dropdown.open .dropdown-menu .fiad-action{right:0}.fiad-action{height:35px;width:35px;background:#ffc107;display:inline-block;border-radius:50%;text-align:center;line-height:35px;font-weight:400;position:relative;top:4px;margin-left:5px;-webkit-animation-name:fiad-action-anim;animation-name:fiad-action-anim;-webkit-transform-origin:center center;transform-origin:center center;-webkit-backface-visibility:none;backface-visibility:none;box-shadow:0 2px 4px rgba(0,0,0,.1)}.fiad-action:nth-child(2){-webkit-animation-duration:.1s;animation-duration:.1s}.fiad-action:first-child{-webkit-animation-duration:.25s;animation-duration:.25s}.fiad-action>i{font-size:14px;color:#fff}.fiad-action:hover{background-color:#f7b900}@-webkit-keyframes fiad-action-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0);right:-20px}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100);right:0}}@keyframes fiad-action-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0);right:-20px}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100);right:0}}.file-explorer{background-color:#fff;position:relative;height:100%}.file-explorer.toggled{height:100vh;overflow:hidden}.fe-body{min-height:100vh;overflow:auto}@media (min-width:992px){.fe-body{padding:0 0 40px 300px}}@media (max-width:991px){.fe-body{padding:75px 0 80px}}.feb-actions{position:fixed;bottom:30px;right:30px}.feb-actions .dropdown-menu{min-width:55px;width:55px;text-align:center;background:transparent;box-shadow:none;margin:0}.feb-actions.open .feba-btn{-webkit-transform:scale(1);transform:scale(1)}.feb-actions.open .feba-btn:first-child{-webkit-animation-name:feba-btn-anim;animation-name:feba-btn-anim;-webkit-animation-duration:.3s;animation-duration:.3s}.feb-actions.open .feba-btn:last-child{-webkit-animation-name:feba-btn-anim;animation-name:feba-btn-anim;-webkit-animation-duration:.1s;animation-duration:.1s}.feb-actions.open .feba-toggle{background:#ff403c}.feb-actions.open .feba-toggle>span{-webkit-transform:rotate(135deg);transform:rotate(135deg)}.feba-toggle{width:55px;height:55px;line-height:55px;border-radius:50%;background:#ff726f;box-shadow:0 2px 3px rgba(0,0,0,.15);display:inline-block;text-align:center;border:0;padding:0}.feba-toggle span{display:inline-block;height:100%;width:100%}.feba-toggle i{color:#fff;font-size:17px;line-height:58px}.feba-toggle,.feba-toggle>span{-webkit-transition:all;transition:all;-webkit-transition-duration:.25s;transition-duration:.25s;-webkit-backface-visibility:hidden;backface-visibility:hidden}.feba-btn{width:40px;margin-top:10px;height:40px;border-radius:50%;text-align:center;display:inline-block;line-height:40px;box-shadow:0 2px 3px rgba(0,0,0,.15);-webkit-transform:scale(0);transform:scale(0);position:relative}.feba-btn,.feba-btn:focus,.feba-btn:hover{color:#fff}.feba-btn label{width:100%;height:100%;position:absolute;left:0;top:0;cursor:pointer}.feba-bucket{background:#ffc155}.feba-upload{background:#ffc107}@-webkit-keyframes feba-btn-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100)}}@keyframes feba-btn-anim{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0;filter:alpha(opacity=0)}to{-webkit-transform:scale(1);transform:scale(1);opacity:1;filter:alpha(opacity=100)}}.ie-warning{background-color:#ff5252;width:100%;height:100%;position:fixed;left:0;top:0;text-align:center}.ie-warning:before{width:1px;content:"";height:100%}.ie-warning .iw-inner,.ie-warning:before{display:inline-block;vertical-align:middle}.iw-inner{width:470px;height:300px;background-color:#fff;border-radius:5px;padding:40px;position:relative}.iw-inner ul{list-style:none;padding:0;margin:0;width:230px;margin-left:80px;margin-top:16px}.iw-inner ul>li{float:left}.iw-inner ul>li>a{display:block;padding:10px 15px 7px;font-size:14px;margin:0 1px;border-radius:3px}.iw-inner ul>li>a:hover{background:#eee}.iw-inner ul>li>a img{height:40px;margin-bottom:5px}.iwi-icon{color:#ff5252;font-size:40px;display:block;line-height:100%;margin-bottom:15px}.iwi-skip{position:absolute;left:0;bottom:-35px;width:100%;color:hsla(0,0%,100%,.6);cursor:pointer}.iwi-skip:hover{color:#fff}.dropdown-menu{padding:15px 0;top:0;margin-top:-1px}.dropdown-menu>li>a{padding:8px 20px;font-size:15px}.dropdown-menu>li>a>i{width:20px;position:relative;top:1px}.dropdown-menu-right>li>a{text-align:right}.alert{border:0;position:fixed;max-width:500px;margin:0;box-shadow:0 4px 5px rgba(0,0,0,.1);color:#fff;width:100%;right:20px;border-radius:3px;padding:17px 50px 17px 17px;z-index:10010;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.alert:not(.progress){top:20px}@media (min-width:768px){.alert:not(.progress){left:50%;margin-left:-250px}}.alert.progress{bottom:20px;right:20px}.alert.alert-danger{background:#ff726f}.alert.alert-success{background:#33d46f}.alert.alert-info{background:#50b2ff}@media (max-width:767px){.alert{left:20px;width:calc(100% - 40px);max-width:100%}}.alert .progress{margin:10px 10px 8px 0;height:5px;box-shadow:none;border-radius:1px;background-color:#50b2ff;border-radius:2px;overflow:hidden}.alert .progress-bar{box-shadow:none;background-color:#fff;height:100%}.alert .close{position:absolute;top:15px}@media (min-width:768px){.modal{text-align:center}.modal:before{content:"";height:100%;width:1px}.modal .modal-dialog,.modal:before{display:inline-block;vertical-align:middle}.modal .modal-dialog{text-align:left;margin:10px auto}}.modal-dark .modal-header{color:hsla(0,0%,100%,.4)}.modal-dark .modal-header small{color:hsla(0,0%,100%,.2)}.modal-dark .modal-content{background-color:#32393f}.modal-backdrop{-webkit-animation-name:fadeIn;animation-name:fadeIn;-webkit-animation-fill-mode:both;animation-fill-mode:both}.modal-backdrop,.modal-dialog{-webkit-animation-duration:.2s;animation-duration:.2s}.modal-dialog{-webkit-animation-name:zoomIn;animation-name:zoomIn;-webkit-animation-fill-mode:both;animation-fill-mode:both}.modal-header{color:#333;position:relative}.modal-header small{display:block;text-transform:none;font-size:12px;margin-top:5px;color:#a8a8a8}.modal-content{border-radius:3px;box-shadow:none}.modal-footer{padding:0 30px 30px}.modal-confirm .modal-dialog,.modal-footer{text-align:center}.mc-icon{margin:0 0 10px}.mc-icon>i{font-size:60px}.mci-red{color:#ff8f8f}.mci-amber{color:#ffc107}.mci-green{color:#64e096}.mc-text{color:#333}.mc-sub{color:#bdbdbd;margin-top:5px;font-size:13px}@media (max-width:767px){.modal-about{text-align:center}.modal-about .modal-dialog{max-width:400px;width:90%;margin:20px auto 0}}.ma-inner{display:flex;flex-direction:row;align-items:center;min-height:350px;position:relative}@media (min-width:768px){.ma-inner:before{content:"";width:150px;height:100%;top:0;left:0;position:absolute;border-radius:3px 0 0 3px;background-color:#23282c}}.mai-item:first-child{width:150px;text-align:center}.mai-item:last-child{flex:4;padding:30px}.maii-logo{width:70px;position:relative}.maii-list{list-style:none;padding:0}.maii-list>li{margin-bottom:15px}.maii-list>li div{color:hsla(0,0%,100%,.8);text-transform:uppercase;font-size:14px}.maii-list>li small{font-size:13px;color:hsla(0,0%,100%,.4)}.toggle-password{position:absolute;bottom:30px;right:35px;width:30px;height:30px;border:1px solid #eee;border-radius:0;text-align:center;cursor:pointer;z-index:10;background-color:#fff;padding-top:5px}.toggle-password.toggled{background:#eee}.pm-body{padding-bottom:30px}.pmb-header{margin-bottom:35px}.pmb-list{display:flex;flex-flow:row nowrap;align-items:center;justify-content:center;padding:10px 35px}.pmb-list:nth-child(2n){background-color:#f7f7f7}.pmb-list .form-control{padding-left:0;padding-right:0}header.pmb-list{margin:20px 0 10px}.pmbl-item{display:block;font-size:13px}.pmbl-item:first-child{flex:2}.pmbl-item:nth-child(2){margin:0 25px;width:150px}.pmbl-item:nth-child(3){width:70px}div.pmb-list select{border:0}div.pmb-list .pml-item:not(:last-child){padding:0 5px}.modal-create-bucket .modal-dialog{position:fixed;right:25px;bottom:95px;margin:0;height:110px}.modal-create-bucket .modal-content{width:100%;height:100%}',""]); },function(A,M,t){function I(A){return null===A||void 0===A}function g(A){return!(!A||"object"!=typeof A||"number"!=typeof A.length)&&("function"==typeof A.copy&&"function"==typeof A.slice&&!(A.length>0&&"number"!=typeof A[0]))}function e(A,M,t){var e,o;if(I(A)||I(M))return!1;if(A.prototype!==M.prototype)return!1;if(E(A))return!!E(M)&&(A=i.call(A),M=i.call(M),N(A,M,t));if(g(A)){if(!g(M))return!1;if(A.length!==M.length)return!1;for(e=0;e=0;e--)if(n[e]!=C[e])return!1;for(e=n.length-1;e>=0;e--)if(o=n[e],!N(A[o],M[o],t))return!1;return typeof A==typeof M}var i=Array.prototype.slice,T=t(280),E=t(279),N=A.exports=function(A,M,t){return t||(t={}),A===M||(A instanceof Date&&M instanceof Date?A.getTime()===M.getTime():!A||!M||"object"!=typeof A&&"object"!=typeof M?t.strict?A===M:A==M:e(A,M,t))}},function(A,M){function t(A){return"[object Arguments]"==Object.prototype.toString.call(A)}function I(A){return A&&"object"==typeof A&&"number"==typeof A.length&&Object.prototype.hasOwnProperty.call(A,"callee")&&!Object.prototype.propertyIsEnumerable.call(A,"callee")||!1}var g="[object Arguments]"==function(){return Object.prototype.toString.call(arguments)}();M=A.exports=g?t:I,M.supported=t,M.unsupported=I},function(A,M){function t(A){var M=[];for(var t in A)M.push(t);return M}M=A.exports="function"==typeof Object.keys?Object.keys:t,M.shim=t},function(A,M,t){"use strict";var I=t(141);A.exports=function(A,M){A.classList?A.classList.add(M):I(A)||(A.className=A.className+" "+M)}},function(A,M,t){"use strict";A.exports={addClass:t(281),removeClass:t(283),hasClass:t(141)}},function(A,M){"use strict";A.exports=function(A,M){A.classList?A.classList.remove(M):A.className=A.className.replace(new RegExp("(^|\\s)"+M+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,"")}},function(A,M,t){"use strict";var I=t(40),g=t(288);A.exports=function(A,M){return function(t){var e=t.currentTarget,i=t.target,T=g(e,A);T.some(function(A){return I(A,i)})&&M.call(this,t)}}},function(A,M,t){"use strict";var I=t(81),g=t(142),e=t(284);A.exports={on:I,off:g,filter:e}},function(A,M,t){"use strict";function I(A){return A.nodeName&&A.nodeName.toLowerCase()}function g(A){for(var M=(0,T.default)(A),t=A&&A.offsetParent;t&&"html"!==I(A)&&"static"===(0,N.default)(t,"position");)t=t.offsetParent;return t||M.documentElement}var e=t(58);M.__esModule=!0,M.default=g;var i=t(39),T=e.interopRequireDefault(i),E=t(82),N=e.interopRequireDefault(E);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A.nodeName&&A.nodeName.toLowerCase()}function g(A,M){var t,g={top:0,left:0};return"fixed"===(0,a.default)(A,"position")?t=A.getBoundingClientRect():(M=M||(0,N.default)(A),t=(0,T.default)(A),"html"!==I(M)&&(g=(0,T.default)(M)),g.top+=parseInt((0,a.default)(M,"borderTopWidth"),10)-(0,n.default)(M)||0,g.left+=parseInt((0,a.default)(M,"borderLeftWidth"),10)-(0,c.default)(M)||0),e._extends({},t,{top:t.top-g.top-(parseInt((0,a.default)(A,"marginTop"),10)||0),left:t.left-g.left-(parseInt((0,a.default)(A,"marginLeft"),10)||0)})}var e=t(58);M.__esModule=!0,M.default=g;var i=t(143),T=e.interopRequireDefault(i),E=t(286),N=e.interopRequireDefault(E),o=t(144),n=e.interopRequireDefault(o),C=t(289),c=e.interopRequireDefault(C),D=t(82),a=e.interopRequireDefault(D);A.exports=M.default},function(A,M){"use strict";var t=/^[\w-]*$/,I=Function.prototype.bind.call(Function.prototype.call,[].slice);A.exports=function(A,M){var g,e="#"===M[0],i="."===M[0],T=e||i?M.slice(1):M,E=t.test(T);return E?e?(A=A.getElementById?A:document,(g=A.getElementById(T))?[g]:[]):I(A.getElementsByClassName&&i?A.getElementsByClassName(T):A.getElementsByTagName(M)):I(A.querySelectorAll(M))}},function(A,M,t){"use strict";var I=t(57);A.exports=function(A,M){var t=I(A);return void 0===M?t?"pageXOffset"in t?t.pageXOffset:t.document.documentElement.scrollLeft:A.scrollLeft:void(t?t.scrollTo(M,"pageYOffset"in t?t.pageYOffset:t.document.documentElement.scrollTop):A.scrollLeft=M)}},function(A,M,t){"use strict";var I=t(58),g=t(145),e=I.interopRequireDefault(g),i=/^(top|right|bottom|left)$/,T=/^([+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/i;A.exports=function(A){if(!A)throw new TypeError("No Element passed to ` + "`" + `getComputedStyle()` + "`" + `");var M=A.ownerDocument;return"defaultView"in M?M.defaultView.opener?A.ownerDocument.defaultView.getComputedStyle(A,null):window.getComputedStyle(A,null):{getPropertyValue:function(M){var t=A.style;M=(0,e.default)(M),"float"==M&&(M="styleFloat");var I=A.currentStyle[M]||null;if(null==I&&t&&t[M]&&(I=t[M]),T.test(I)&&!i.test(M)){var g=t.left,E=A.runtimeStyle,N=E&&E.left;N&&(E.left=A.currentStyle.left),t.left="fontSize"===M?"1em":I,I=t.pixelLeft+"px",t.left=g,N&&(E.left=N)}return I}}}},function(A,M){"use strict";A.exports=function(A,M){return"removeProperty"in A.style?A.style.removeProperty(M):A.style.removeAttribute(M)}},function(A,M,t){"use strict";function I(){var A,M="",t={O:"otransitionend",Moz:"transitionend",Webkit:"webkitTransitionEnd",ms:"MSTransitionEnd"},I=document.createElement("div");for(var g in t)if(N.call(t,g)&&void 0!==I.style[g+"TransitionProperty"]){M="-"+g.toLowerCase()+"-",A=t[g];break}return A||void 0===I.style.transitionProperty||(A="transitionend"),{end:A,prefix:M}}var g,e,i,T,E=t(32),N=Object.prototype.hasOwnProperty,o="transform",n={};E&&(n=I(),o=n.prefix+o,i=n.prefix+"transition-property",e=n.prefix+"transition-duration",T=n.prefix+"transition-delay",g=n.prefix+"transition-timing-function"),A.exports={transform:o,end:n.end,property:i,timing:g,delay:T,duration:e}},function(A,M){"use strict";var t=/-(.)/g;A.exports=function(A){return A.replace(t,function(A,M){return M.toUpperCase()})}},function(A,M){"use strict";var t=/([A-Z])/g;A.exports=function(A){return A.replace(t,"-$1").toLowerCase()}},function(A,M,t){"use strict";var I=t(294),g=/^ms-/;A.exports=function(A){return I(A).replace(g,"-ms-")}},function(A,M){"use strict";function t(A){return A.replace(I,function(A,M){return M.toUpperCase()})}var I=/-(.)/g;A.exports=t},function(A,M,t){"use strict";function I(A){return g(A.replace(e,"ms-"))}var g=t(296),e=/^-ms-/;A.exports=I},function(A,M,t){"use strict";function I(A){return!!A&&("object"==typeof A||"function"==typeof A)&&"length"in A&&!("setInterval"in A)&&"number"!=typeof A.nodeType&&(Array.isArray(A)||"callee"in A||"item"in A)}function g(A){return I(A)?Array.isArray(A)?A.slice():e(A):[A]}var e=t(307);A.exports=g},function(A,M,t){"use strict";function I(A){var M=A.match(o);return M&&M[1].toLowerCase()}function g(A,M){var t=N;N?void 0:E(!1);var g=I(A),e=g&&T(g);if(e){t.innerHTML=e[1]+A+e[2];for(var o=e[0];o--;)t=t.lastChild}else t.innerHTML=A;var n=t.getElementsByTagName("script");n.length&&(M?void 0:E(!1),i(n).forEach(M));for(var C=i(t.childNodes);t.lastChild;)t.removeChild(t.lastChild);return C}var e=t(10),i=t(298),T=t(151),E=t(2),N=e.canUseDOM?document.createElement("div"):null,o=/^\s*<(\w+)/;A.exports=g},function(A,M){"use strict";function t(A){return A===window?{x:window.pageXOffset||document.documentElement.scrollLeft,y:window.pageYOffset||document.documentElement.scrollTop}:{x:A.scrollLeft,y:A.scrollTop}}A.exports=t},function(A,M){"use strict";function t(A){return A.replace(I,"-$1").toLowerCase()}var I=/([A-Z])/g;A.exports=t},function(A,M,t){"use strict";function I(A){return g(A).replace(e,"-ms-")}var g=t(301),e=/^ms-/;A.exports=I},function(A,M){"use strict";function t(A){return!(!A||!("function"==typeof Node?A instanceof Node:"object"==typeof A&&"number"==typeof A.nodeType&&"string"==typeof A.nodeName))}A.exports=t},function(A,M,t){"use strict";function I(A){return g(A)&&3==A.nodeType}var g=t(303);A.exports=I},function(A,M){"use strict";function t(A,M,t){if(!A)return null;var g={};for(var e in A)I.call(A,e)&&(g[e]=M.call(t,A[e],e,A));return g}var I=Object.prototype.hasOwnProperty;A.exports=t},function(A,M){"use strict";function t(A){var M={};return function(t){return M.hasOwnProperty(t)||(M[t]=A.call(this,t)),M[t]}}A.exports=t},function(A,M,t){"use strict";function I(A){var M=A.length;if(Array.isArray(A)||"object"!=typeof A&&"function"!=typeof A?g(!1):void 0,"number"!=typeof M?g(!1):void 0,0===M||M-1 in A?void 0:g(!1),A.hasOwnProperty)try{return Array.prototype.slice.call(A)}catch(A){}for(var t=Array(M),I=0;Io||N===o&&"application/"===M[T].substr(0,12))continue}M[T]=I}}})}var E=t(351),N=t(354).extname,o=/^\s*([^;\s]*)(?:;|\s|$)/,n=/^text\//i;M.charset=I,M.charsets={lookup:I},M.contentType=g,M.extension=e,M.extensions=Object.create(null),M.lookup=i,M.types=Object.create(null),T(M.extensions,M.types)},function(A,M){function t(A){throw new Error("Cannot find module '"+A+"'.")}t.keys=function(){return[]},t.resolve=t,A.exports=t,t.id=353},function(A,M,t){(function(A){function t(A,M){for(var t=0,I=A.length-1;I>=0;I--){var g=A[I];"."===g?A.splice(I,1):".."===g?(A.splice(I,1),t++):t&&(A.splice(I,1),t--)}if(M)for(;t--;t)A.unshift("..");return A}function I(A,M){if(A.filter)return A.filter(M);for(var t=[],I=0;I=-1&&!g;e--){var i=e>=0?arguments[e]:A.cwd();if("string"!=typeof i)throw new TypeError("Arguments to path.resolve must be strings");i&&(M=i+"/"+M,g="/"===i.charAt(0))}return M=t(I(M.split("/"),function(A){return!!A}),!g).join("/"),(g?"/":"")+M||"."},M.normalize=function(A){var g=M.isAbsolute(A),e="/"===i(A,-1);return A=t(I(A.split("/"),function(A){return!!A}),!g).join("/"),A||g||(A="."),A&&e&&(A+="/"),(g?"/":"")+A},M.isAbsolute=function(A){return"/"===A.charAt(0)},M.join=function(){var A=Array.prototype.slice.call(arguments,0);return M.normalize(I(A,function(A,M){if("string"!=typeof A)throw new TypeError("Arguments to path.join must be strings");return A}).join("/"))},M.relative=function(A,t){function I(A){for(var M=0;M=0&&""===A[t];t--);return M>t?[]:A.slice(M,t-M+1)}A=M.resolve(A).substr(1),t=M.resolve(t).substr(1);for(var g=I(A.split("/")),e=I(t.split("/")),i=Math.min(g.length,e.length),T=i,E=0;E=0;e--){var i=I[e]+g;if(i in M)return i}return!1}},function(A,M,t){"use strict";var I=t(496);M.extract=function(A){return A.split("?")[1]||""},M.parse=function(A){return"string"!=typeof A?{}:(A=A.trim().replace(/^(\?|#|&)/,""),A?A.split("&").reduce(function(A,M){var t=M.replace(/\+/g," ").split("="),I=t.shift(),g=t.length>0?t.join("="):void 0;return I=decodeURIComponent(I),g=void 0===g?null:decodeURIComponent(g),A.hasOwnProperty(I)?Array.isArray(A[I])?A[I].push(g):A[I]=[A[I],g]:A[I]=g,A},{}):{})},M.stringify=function(A){return A?Object.keys(A).sort().map(function(M){var t=A[M];return void 0===t?"":null===t?M:Array.isArray(t)?t.slice().sort().map(function(A){return I(M)+"="+I(A)}).join("&"):I(M)+"="+I(t)}).filter(function(A){return A.length>0}).join("&"):""}},function(A,M){"use strict";function t(A,M){return Object.prototype.hasOwnProperty.call(A,M)}A.exports=function(A,M,I,g){M=M||"&",I=I||"=";var e={};if("string"!=typeof A||0===A.length)return e;var i=/\+/g;A=A.split(M);var T=1e3;g&&"number"==typeof g.maxKeys&&(T=g.maxKeys);var E=A.length;T>0&&E>T&&(E=T);for(var N=0;N=0?(o=D.substr(0,a),n=D.substr(a+1)):(o=D,n=""),C=decodeURIComponent(o),c=decodeURIComponent(n),t(e,C)?Array.isArray(e[C])?e[C].push(c):e[C]=[e[C],c]:e[C]=c}return e}},function(A,M){"use strict";var t=function(A){switch(typeof A){case"string":return A;case"boolean":return A?"true":"false";case"number":return isFinite(A)?A:"";default:return""}};A.exports=function(A,M,I,g){return M=M||"&",I=I||"=",null===A&&(A=void 0),"object"==typeof A?Object.keys(A).map(function(g){var e=encodeURIComponent(t(g))+I;return Array.isArray(A[g])?A[g].map(function(A){return e+encodeURIComponent(t(A))}).join(M):e+encodeURIComponent(t(A[g]))}).join(M):g?encodeURIComponent(t(g))+I+encodeURIComponent(t(A)):""}},function(A,M,t){"use strict";M.decode=M.parse=t(358),M.encode=M.stringify=t(359)},function(A,M,t){(function(M){for(var I=t(355),g="undefined"==typeof window?M:window,e=["moz","webkit"],i="AnimationFrame",T=g["request"+i],E=g["cancel"+i]||g["cancelRequest"+i],N=0;!T&&N1)||(e=A,!1)}),e)return new Error("(children) "+I+" - Duplicate children detected of bsRole: "+e+". Only one child each allowed with the following bsRoles: "+M.join(", "))})}},A.exports=M.default},function(A,M,t){"use strict";function I(A){var M=[];return void 0===A?M:(i.default.forEach(A,function(A){M.push(A)}),M)}var g=t(6).default;M.__esModule=!0,M.default=I;var e=t(51),i=g(e);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}Object.defineProperty(M,"__esModule",{value:!0}),M.CopyToClipboard=void 0;var e=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){var M=A.style,t=g(A,["style"]),I=o({},M,{height:6,right:2,bottom:2,left:2,borderRadius:3});return C.default.createElement("div",o({style:I},t))}function i(A){var M=A.style,t=g(A,["style"]),I=o({},M,{width:6,right:2,bottom:2,top:2,borderRadius:3});return C.default.createElement("div",o({style:I},t))}function T(A){var M=A.style,t=g(A,["style"]),I=o({},M,{cursor:"pointer",borderRadius:"inherit",backgroundColor:"rgba(0,0,0,.2)"});return C.default.createElement("div",o({style:I},t))}function E(A){var M=A.style,t=g(A,["style"]),I=o({},M,{cursor:"pointer",borderRadius:"inherit",backgroundColor:"rgba(0,0,0,.2)"});return C.default.createElement("div",o({style:I},t))}function N(A){return C.default.createElement("div",A)}var o=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}var e=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=Object.assign||function(A){for(var M=1;M0||(this.setState({isDragActive:!1,isDragReject:!1}),this.props.onDragLeave&&this.props.onDragLeave.call(this,A))}},{key:"onDrop",value:function A(M){var t=this,I=this.props,A=I.onDrop,g=I.onDropAccepted,e=I.onDropRejected,i=I.multiple,T=I.disablePreview,E=(0,a.default)(M,i),N=[],o=[];M.preventDefault(),this.enterCounter=0,this.isFileDialogActive=!1,E.forEach(function(A){T||(A.preview=window.URL.createObjectURL(A)),t.fileAccepted(A)&&t.fileMatchSize(A)?N.push(A):o.push(A)}),A&&A.call(this,N,o,M),o.length>0&&e&&e.call(this,o,M),N.length>0&&g&&g.call(this,N,M),this.setState({isDragActive:!1,isDragReject:!1})}},{key:"onClick",value:function A(M){M.stopPropagation();var t=this.props,A=t.onClick,I=t.disableClick;I||(this.open(),A&&A.call(this,M))}},{key:"onFileDialogCancel",value:function A(){var A=this.props.onFileDialogCancel,M=this.fileInputEl,t=this.isFileDialogActive;A&&t&&setTimeout(function(){var I=M.files;I.length||(t=!1,A())},300)}},{key:"fileAccepted",value:function(A){return(0,c.default)(A,this.props.accept)}},{key:"fileMatchSize",value:function(A){return A.size<=this.props.maxSize&&A.size>=this.props.minSize}},{key:"allFilesAccepted",value:function(A){return A.every(this.fileAccepted)}},{key:"open",value:function(){this.isFileDialogActive=!0,this.fileInputEl.value=null,this.fileInputEl.click()}},{key:"render",value:function(){var A=this,M=this.props,t=M.accept,I=M.activeClassName,e=M.inputProps,i=M.multiple,T=M.name,N=M.rejectClassName,o=g(M,["accept","activeClassName","inputProps","multiple","name","rejectClassName"]),C=o.activeStyle,c=o.className,D=o.rejectStyle,a=o.style,Q=g(o,["activeStyle","className","rejectStyle","style"]),r=this.state,s=r.isDragActive,x=r.isDragReject;c=c||"",s&&I&&(c+=" "+I),x&&N&&(c+=" "+N),c||a||C||D||(a={width:200,height:200,borderWidth:2,borderColor:"#666",borderStyle:"dashed",borderRadius:5},C={borderStyle:"solid",backgroundColor:"#eee"},D={borderStyle:"solid",backgroundColor:"#ffdddd"});var j=void 0;j=C&&s?E({},a,C):D&&x?E({},a,D):E({},a);var y={accept:t,type:"file",style:{display:"none"},multiple:B&&i,ref:function(M){return A.fileInputEl=M},onChange:this.onDrop};T&&T.length&&(y.name=T);var u=["acceptedFiles","disablePreview","disableClick","onDropAccepted","onDropRejected","onFileDialogCancel","maxSize","minSize"],w=E({},Q);return u.forEach(function(A){return delete w[A]}),n.default.createElement("div",E({className:c,style:j},w,{onClick:this.onClick,onDragStart:this.onDragStart,onDragEnter:this.onDragEnter,onDragOver:this.onDragOver,onDragLeave:this.onDragLeave,onDrop:this.onDrop}),this.props.children,n.default.createElement("input",E({},e,y)))}}]),M}(n.default.Component);Q.defaultProps={disablePreview:!1,disableClick:!1,multiple:!0,maxSize:1/0,minSize:0},Q.propTypes={onClick:n.default.PropTypes.func,onDrop:n.default.PropTypes.func,onDropAccepted:n.default.PropTypes.func,onDropRejected:n.default.PropTypes.func,onDragStart:n.default.PropTypes.func,onDragEnter:n.default.PropTypes.func,onDragOver:n.default.PropTypes.func,onDragLeave:n.default.PropTypes.func,children:n.default.PropTypes.node,style:n.default.PropTypes.object,activeStyle:n.default.PropTypes.object,rejectStyle:n.default.PropTypes.object,className:n.default.PropTypes.string,activeClassName:n.default.PropTypes.string,rejectClassName:n.default.PropTypes.string,disablePreview:n.default.PropTypes.bool,disableClick:n.default.PropTypes.bool,onFileDialogCancel:n.default.PropTypes.func,inputProps:n.default.PropTypes.object,multiple:n.default.PropTypes.bool,accept:n.default.PropTypes.string,name:n.default.PropTypes.string,maxSize:n.default.PropTypes.number,minSize:n.default.PropTypes.number},M.default=Q,A.exports=M.default},function(M,t){M.exports=A},function(A,M){A.exports=function(A){function M(I){if(t[I])return t[I].exports;var g=t[I]={exports:{},id:I,loaded:!1};return A[I].call(g.exports,g,g.exports,M),g.loaded=!0,g.exports}var t={};return M.m=A,M.c=t,M.p="",M(0)}([function(A,M,t){"use strict";M.__esModule=!0,t(8),t(9),M.default=function(A,M){if(A&&M){var t=function(){var t=Array.isArray(M)?M:M.split(","),I=A.name||"",g=A.type||"",e=g.replace(/\/.*$/,"");return{v:t.some(function(A){var M=A.trim();return"."===M.charAt(0)?I.toLowerCase().endsWith(M.toLowerCase()):/\/\*$/.test(M)?e===M.replace(/\/.*$/,""):g===M})}}();if("object"==typeof t)return t.v}return!0},A.exports=M.default},function(A,M){var t=A.exports={version:"1.2.2"};"number"==typeof __e&&(__e=t)},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(2),g=t(1),e=t(4),i=t(19),T="prototype",E=function(A,M){return function(){return A.apply(M,arguments)}},N=function(A,M,t){var o,n,C,c,D=A&N.G,a=A&N.P,B=D?I:A&N.S?I[M]||(I[M]={}):(I[M]||{})[T],Q=D?g:g[M]||(g[M]={});D&&(t=M);for(o in t)n=!(A&N.F)&&B&&o in B,C=(n?B:t)[o],c=A&N.B&&n?E(C,I):a&&"function"==typeof C?E(Function.call,C):C,B&&!n&&i(B,o,C),Q[o]!=C&&e(Q,o,c),a&&((Q[T]||(Q[T]={}))[o]=C)};I.core=g,N.F=1,N.G=2,N.S=4,N.P=8,N.B=16,N.W=32,A.exports=N},function(A,M,t){var I=t(5),g=t(18);A.exports=t(22)?function(A,M,t){return I.setDesc(A,M,g(1,t))}:function(A,M,t){return A[M]=t,A}},function(A,M){var t=Object;A.exports={create:t.create,getProto:t.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:t.getOwnPropertyDescriptor,setDesc:t.defineProperty,setDescs:t.defineProperties,getKeys:t.keys,getNames:t.getOwnPropertyNames,getSymbols:t.getOwnPropertySymbols,each:[].forEach}},function(A,M){var t=0,I=Math.random();A.exports=function(A){return"Symbol(".concat(void 0===A?"":A,")_",(++t+I).toString(36))}},function(A,M,t){var I=t(20)("wks"),g=t(2).Symbol;A.exports=function(A){return I[A]||(I[A]=g&&g[A]||(g||t(6))("Symbol."+A))}},function(A,M,t){t(26),A.exports=t(1).Array.some},function(A,M,t){t(25),A.exports=t(1).String.endsWith},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M,t){var I=t(10);A.exports=function(A,M,t){if(I(A),void 0===M)return A;switch(t){case 1:return function(t){return A.call(M,t)};case 2:return function(t,I){return A.call(M,t,I)};case 3:return function(t,I,g){return A.call(M,t,I,g)}}return function(){return A.apply(M,arguments)}}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M,t){A.exports=function(A){var M=/./;try{"/./"[A](M)}catch(I){try{return M[t(7)("match")]=!1,!"/./"[A](M)}catch(A){}}return!0}},function(A,M){A.exports=function(A){try{return!!A()}catch(A){return!0}}},function(A,M){A.exports=function(A){return"object"==typeof A?null!==A:"function"==typeof A}},function(A,M,t){var I=t(16),g=t(11),e=t(7)("match");A.exports=function(A){var M;return I(A)&&(void 0!==(M=A[e])?!!M:"RegExp"==g(A))}},function(A,M){A.exports=function(A,M){return{enumerable:!(1&A),configurable:!(2&A),writable:!(4&A),value:M}}},function(A,M,t){var I=t(2),g=t(4),e=t(6)("src"),i="toString",T=Function[i],E=(""+T).split(i);t(1).inspectSource=function(A){return T.call(A)},(A.exports=function(A,M,t,i){"function"==typeof t&&(g(t,e,A[M]?""+A[M]:E.join(String(M))),"name"in t||(t.name=M)),A===I?A[M]=t:(i||delete A[M],g(A,M,t))})(Function.prototype,i,function(){return"function"==typeof this&&this[e]||T.call(this)})},function(A,M,t){var I=t(2),g="__core-js_shared__",e=I[g]||(I[g]={});A.exports=function(A){return e[A]||(e[A]={})}},function(A,M,t){var I=t(17),g=t(13);A.exports=function(A,M,t){if(I(M))throw TypeError("String#"+t+" doesn't accept regex!");return String(g(A))}},function(A,M,t){A.exports=!t(15)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(A,M){var t=Math.ceil,I=Math.floor;A.exports=function(A){return isNaN(A=+A)?0:(A>0?I:t)(A)}},function(A,M,t){var I=t(23),g=Math.min;A.exports=function(A){return A>0?g(I(A),9007199254740991):0}},function(A,M,t){"use strict";var I=t(3),g=t(24),e=t(21),i="endsWith",T=""[i];I(I.P+I.F*t(14)(i),"String",{endsWith:function(A){var M=e(this,A,i),t=arguments,I=t.length>1?t[1]:void 0,E=g(M.length),N=void 0===I?E:Math.min(g(I),E),o=String(A);return T?T.call(M,o,N):M.slice(N-o.length,N)===o}})},function(A,M,t){var I=t(5),g=t(3),e=t(1).Array||Array,i={},T=function(A,M){I.each.call(A.split(","),function(A){void 0==M&&A in e?i[A]=e[A]:A in[]&&(i[A]=t(12)(Function.call,[][A],M))})};T("pop,reverse,shift,keys,values,entries",1),T("indexOf,every,some,forEach,map,filter,find,findIndex,includes",3),T("join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill"),g(g.S,"Array",i)}])},function(A,M){"use strict";function t(A){var M=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],t=[];if(A.dataTransfer){var I=A.dataTransfer;I.files&&I.files.length?t=I.files:I.items&&I.items.length&&(t=I.items)}else A.target&&A.target.files&&(t=A.target.files);return t.length>0&&(t=M?t:[t[0]]),Array.prototype.slice.call(t)}Object.defineProperty(M,"__esModule",{value:!0}),M.default=t,A.exports=M.default}])})},function(A,M,t){"use strict";function I(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function g(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}var e=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{},t=M.hideSiblingNodes,I=void 0===t||t,e=M.handleContainerOverflow,i=void 0===e||e;g(this,A),this.hideSiblingNodes=I,this.handleContainerOverflow=i,this.modals=[],this.containers=[],this.data=[]}return N(A,[{key:"add",value:function(A,M,t){var I=this.modals.indexOf(A),g=this.containers.indexOf(M);if(I!==-1)return I;if(I=this.modals.length,this.modals.push(A),this.hideSiblingNodes&&(0,r.hideSiblings)(M,A.mountNode),g!==-1)return this.data[g].modals.push(A),I;var e={modals:[A],classes:t?t.split(/\s+/):[],overflowing:(0,Q.default)(M)};return this.handleContainerOverflow&&T(e,M),e.classes.forEach(c.default.addClass.bind(null,M)),this.containers.push(M),this.data.push(e),I}},{key:"remove",value:function(A){var M=this.modals.indexOf(A);if(M!==-1){var t=i(this.data,A),I=this.data[t],g=this.containers[t];I.modals.splice(I.modals.indexOf(A),1),this.modals.splice(M,1),0===I.modals.length?(I.classes.forEach(c.default.removeClass.bind(null,g)),this.handleContainerOverflow&&E(I,g),this.hideSiblingNodes&&(0,r.showSiblings)(g,A.mountNode),this.containers.splice(t,1),this.data.splice(t,1)):this.hideSiblingNodes&&(0,r.ariaHidden)(!1,I.modals[I.modals.length-1].mountNode)}}},{key:"isTopModal",value:function(A){return!!this.modals.length&&this.modals[this.modals.length-1]===A}}]),A}();M.default=s,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=Object.assign||function(A){for(var M=1;M1?t-1:0),g=1;g=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}function E(){}Object.defineProperty(M,"__esModule",{value:!0}),M.EXITING=M.ENTERED=M.ENTERING=M.EXITED=M.UNMOUNTED=void 0;var N=Object.assign||function(A){for(var M=1;MT?T-N:0}function i(A,M,t,I){var e=g(t),i=e.width,T=A-I,E=A+I+M;return T<0?-T:E>i?i-E:0}function T(A,M,t,I,g){var T="BODY"===I.tagName?(0,N.default)(t):(0,n.default)(t,I),E=(0,N.default)(M),o=E.height,C=E.width,c=void 0,D=void 0,a=void 0,B=void 0;if("left"===A||"right"===A){D=T.top+(T.height-o)/2,c="left"===A?T.left-C:T.left+T.width;var Q=e(D,o,I,g);D+=Q,B=50*(1-2*Q/o)+"%",a=void 0}else{if("top"!==A&&"bottom"!==A)throw new Error('calcOverlayPosition(): No such placement of "'+A+'" found.');c=T.left+(T.width-C)/2,D="top"===A?T.top-o:T.top+T.height;var r=i(c,C,I,g);c+=r,a=50*(1-2*r/C)+"%",B=void 0}return{positionLeft:c,positionTop:D,arrowOffsetLeft:a,arrowOffsetTop:B}}Object.defineProperty(M,"__esModule",{value:!0}),M.default=T;var E=t(143),N=I(E),o=t(287),n=I(o),C=t(144),c=I(C),D=t(52),a=I(D);A.exports=M.default},function(A,M){"use strict";function t(A,M){M&&(A?M.setAttribute("aria-hidden","true"):M.removeAttribute("aria-hidden"))}function I(A,M){T(A,M,function(A){return t(!0,A)})}function g(A,M){T(A,M,function(A){return t(!1,A)})}Object.defineProperty(M,"__esModule",{value:!0}),M.ariaHidden=t,M.hideSiblings=I,M.showSiblings=g;var e=["template","script","style"],i=function(A){var M=A.nodeType,t=A.tagName;return 1===M&&e.indexOf(t.toLowerCase())===-1},T=function(A,M,t){M=[].concat(M),[].forEach.call(A.children,function(A){M.indexOf(A)===-1&&i(A)&&t(A)})}},function(A,M,t){"use strict";var I=function(){};A.exports=I},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){return function(t,I,g){if(null!=t[I]){var e='"'+I+'" property of "'+g+'" has been deprecated.\n'+M;E[e]||(T.default(!1,e),E[e]=!0)}return A(t,I,g)}}function e(){E={}}M.__esModule=!0,M.default=g;var i=t(127),T=I(i),E={};g._resetWarned=e,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function e(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function i(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}M.__esModule=!0,M.default=void 0;var T=t(1),E=t(184),N=I(E),o=t(185),n=(I(o),function(A){function M(t,I){g(this,M);var i=e(this,A.call(this,t,I));return i.store=t.store,i}return i(M,A),M.prototype.getChildContext=function(){return{store:this.store}},M.prototype.render=function(){return T.Children.only(this.props.children)},M}(T.Component));M.default=n,n.propTypes={store:N.default.isRequired,children:T.PropTypes.element.isRequired},n.childContextTypes={store:N.default.isRequired}},function(A,M){"use strict";function t(A,M){if(A===M)return!0;var t=Object.keys(A),I=Object.keys(M);if(t.length!==I.length)return!1;for(var g=Object.prototype.hasOwnProperty,e=0;e=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){var t=A.history,I=A.routes,e=A.location,E=g(A,["history","routes","location"]);t||e?void 0:(0,N.default)(!1),t=t?t:(0,n.default)(E);var o=(0,c.default)(t,(0,D.createRoutes)(I)),C=void 0;e?e=t.createLocation(e):C=t.listen(function(A){e=A});var B=(0,a.createRouterObject)(t,o);t=(0,a.createRoutingHistory)(t,o),o.match(e,function(A,I,g){M(A,I&&B.createLocation(I,T.REPLACE),g&&i({},g,{history:t,router:B,matchContext:{history:t,transitionManager:o,router:B}})),C&&C()})}M.__esModule=!0;var i=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return function(){var M=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],t=M.routes,I=g(M,["routes"]),e=(0,E.default)(A)(I),T=(0,o.default)(e,t);return i({},e,T)}}M.__esModule=!0;var i=Object.assign||function(A){for(var M=1;M=A&&N&&(T=!0,t()))}}var i=0,T=!1,E=!1,N=!1,o=void 0;e()}M.__esModule=!0;var I=Array.prototype.slice;M.loopAsync=t},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(){function A(A){try{A=A||window.history.state||{}}catch(M){A={}}var M=n.getWindowPath(),t=A,I=t.key,g=void 0;I?g=C.readState(I):(g=null,I=s.createKey(),Q&&window.history.replaceState(e({},A,{key:I}),null));var i=N.parsePath(M);return s.createLocation(e({},i,{state:g}),void 0,I)}function M(M){function t(M){void 0!==M.state&&I(A(M.state))}var I=M.transitionTo;return n.addEventListener(window,"popstate",t),function(){n.removeEventListener(window,"popstate",t)}}function t(A){var M=A.basename,t=A.pathname,I=A.search,g=A.hash,e=A.state,i=A.action,T=A.key;if(i!==E.POP){C.saveState(T,e);var N=(M||"")+t+I+g,o={key:T};if(i===E.PUSH){if(r)return window.location.href=N,!1;window.history.pushState(o,null,N)}else{if(r)return window.location.replace(N),!1;window.history.replaceState(o,null,N)}}}function I(A){1===++x&&(j=M(s));var t=s.listenBefore(A);return function(){t(),0===--x&&j()}}function g(A){1===++x&&(j=M(s));var t=s.listen(A);return function(){t(),0===--x&&j()}}function i(A){1===++x&&(j=M(s)),s.registerTransitionHook(A)}function c(A){s.unregisterTransitionHook(A),0===--x&&j()}var a=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];o.canUseDOM?void 0:T.default(!1);var B=a.forceRefresh,Q=n.supportsHistory(),r=!Q||B,s=D.default(e({},a,{getCurrentLocation:A,finishTransition:t,saveState:C.saveState})),x=0,j=void 0;return e({},s,{listenBefore:I,listen:g,registerTransitionHook:i,unregisterTransitionHook:c})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M=0&&M=0&&B8&&u<=11),l=32,Y=String.fromCharCode(l),d=c.topLevelTypes,h={beforeInput:{phasedRegistrationNames:{bubbled:s({onBeforeInput:null}),captured:s({onBeforeInputCapture:null})},dependencies:[d.topCompositionEnd,d.topKeyPress,d.topTextInput,d.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:s({onCompositionEnd:null}),captured:s({onCompositionEndCapture:null})},dependencies:[d.topBlur,d.topCompositionEnd,d.topKeyDown,d.topKeyPress,d.topKeyUp,d.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:s({onCompositionStart:null}),captured:s({onCompositionStartCapture:null})},dependencies:[d.topBlur,d.topCompositionStart,d.topKeyDown,d.topKeyPress,d.topKeyUp,d.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:s({onCompositionUpdate:null}),captured:s({onCompositionUpdateCapture:null})},dependencies:[d.topBlur,d.topCompositionUpdate,d.topKeyDown,d.topKeyPress,d.topKeyUp,d.topMouseDown]}},S=!1,z=null,U={eventTypes:h,extractEvents:function(A,M,t,I,g){return[N(A,M,t,I,g),C(A,M,t,I,g)]}};A.exports=U},function(A,M,t){"use strict";var I=t(202),g=t(10),e=t(17),i=(t(297),t(475)),T=t(302),E=t(306),N=(t(3),E(function(A){return T(A)})),o=!1,n="cssFloat";if(g.canUseDOM){var C=document.createElement("div").style;try{C.font=""}catch(A){o=!0}void 0===document.documentElement.style.cssFloat&&(n="styleFloat")}var c={createMarkupForStyles:function(A){var M="";for(var t in A)if(A.hasOwnProperty(t)){var I=A[t];null!=I&&(M+=N(t)+":",M+=i(t,I)+";")}return M||null},setValueForStyles:function(A,M){var t=A.style;for(var g in M)if(M.hasOwnProperty(g)){var e=i(g,M[g]);if("float"===g&&(g=n),e)t[g]=e;else{var T=o&&I.shorthandPropertyExpansions[g];if(T)for(var E in T)t[E]="";else t[g]=""}}}};e.measureMethods(c,"CSSPropertyOperations",{setValueForStyles:"setValueForStyles"}),A.exports=c},function(A,M,t){"use strict";function I(A){var M=A.nodeName&&A.nodeName.toLowerCase();return"select"===M||"input"===M&&"file"===A.type}function g(A){var M=u.getPooled(h.change,z,A,w(A));x.accumulateTwoPhaseDispatches(M),y.batchedUpdates(e,M)}function e(A){s.enqueueEvents(A),s.processEventQueue(!1)}function i(A,M){S=A,z=M,S.attachEvent("onchange",g)}function T(){S&&(S.detachEvent("onchange",g),S=null,z=null)}function E(A,M,t){if(A===d.topChange)return t}function N(A,M,t){A===d.topFocus?(T(),i(M,t)):A===d.topBlur&&T()}function o(A,M){S=A,z=M,U=A.value,p=Object.getOwnPropertyDescriptor(A.constructor.prototype,"value"),Object.defineProperty(S,"value",F),S.attachEvent("onpropertychange",C)}function n(){S&&(delete S.value,S.detachEvent("onpropertychange",C),S=null,z=null,U=null,p=null)}function C(A){if("value"===A.propertyName){var M=A.srcElement.value;M!==U&&(U=M,g(A))}}function c(A,M,t){if(A===d.topInput)return t}function D(A,M,t){A===d.topFocus?(n(),o(M,t)):A===d.topBlur&&n()}function a(A,M,t){if((A===d.topSelectionChange||A===d.topKeyUp||A===d.topKeyDown)&&S&&S.value!==U)return U=S.value,z}function B(A){return A.nodeName&&"input"===A.nodeName.toLowerCase()&&("checkbox"===A.type||"radio"===A.type)}function Q(A,M,t){if(A===d.topClick)return t}var r=t(24),s=t(53),x=t(54),j=t(10),y=t(18),u=t(37),w=t(117),L=t(120),l=t(229),Y=t(27),d=r.topLevelTypes,h={ -change:{phasedRegistrationNames:{bubbled:Y({onChange:null}),captured:Y({onChangeCapture:null})},dependencies:[d.topBlur,d.topChange,d.topClick,d.topFocus,d.topInput,d.topKeyDown,d.topKeyUp,d.topSelectionChange]}},S=null,z=null,U=null,p=null,O=!1;j.canUseDOM&&(O=L("change")&&(!("documentMode"in document)||document.documentMode>8));var m=!1;j.canUseDOM&&(m=L("input")&&(!("documentMode"in document)||document.documentMode>9));var F={get:function(){return p.get.call(this)},set:function(A){U=""+A,p.set.call(this,A)}},f={eventTypes:h,extractEvents:function(A,M,t,g,e){var i,T;if(I(M)?O?i=E:T=N:l(M)?m?i=c:(i=a,T=D):B(M)&&(i=Q),i){var o=i(A,M,t);if(o){var n=u.getPooled(h.change,o,g,e);return n.type="change",x.accumulateTwoPhaseDispatches(n),n}}T&&T(A,M,t)}};A.exports=f},function(A,M){"use strict";var t=0,I={createReactRootIndex:function(){return t++}};A.exports=I},function(A,M,t){"use strict";function I(A){return A.substring(1,A.indexOf(" "))}var g=t(10),e=t(299),i=t(20),T=t(151),E=t(2),N=/^(<[^ \/>]+)/,o="data-danger-index",n={dangerouslyRenderMarkup:function(A){g.canUseDOM?void 0:E(!1);for(var M,t={},n=0;n1?1-M:void 0;return this._fallbackText=g.slice(A,T),this._fallbackText}}),g.addPoolingTo(I),A.exports=I},function(A,M,t){"use strict";var I,g=t(47),e=t(10),i=g.injection.MUST_USE_ATTRIBUTE,T=g.injection.MUST_USE_PROPERTY,E=g.injection.HAS_BOOLEAN_VALUE,N=g.injection.HAS_SIDE_EFFECTS,o=g.injection.HAS_NUMERIC_VALUE,n=g.injection.HAS_POSITIVE_NUMERIC_VALUE,C=g.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(e.canUseDOM){var c=document.implementation;I=c&&c.hasFeature&&c.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var D={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,acceptCharset:null,accessKey:null,action:null,allowFullScreen:i|E,allowTransparency:i,alt:null,async:E,autoComplete:null,autoPlay:E,capture:i|E,cellPadding:null,cellSpacing:null,charSet:i,challenge:i,checked:T|E,classID:i,className:I?i:T,cols:i|n,colSpan:null,content:null,contentEditable:null,contextMenu:i,controls:T|E,coords:null,crossOrigin:null,data:null,dateTime:i,default:E,defer:E,dir:null,disabled:i|E,download:C,draggable:null,encType:null,form:i,formAction:i,formEncType:i,formMethod:i,formNoValidate:E,formTarget:i,frameBorder:i,headers:null,height:i,hidden:i|E,high:null,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:T,inputMode:i,integrity:null,is:i,keyParams:i,keyType:i,kind:null,label:null,lang:null,list:i,loop:T|E,low:null,manifest:i,marginHeight:null,marginWidth:null,max:null,maxLength:i,media:i,mediaGroup:null,method:null,min:null,minLength:i,multiple:T|E,muted:T|E,name:null,nonce:i,noValidate:E,open:E,optimum:null,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:T|E,rel:null,required:E,reversed:E,role:i,rows:i|n,rowSpan:null,sandbox:null,scope:null,scoped:E,scrolling:null,seamless:i|E,selected:T|E,shape:null,size:i|n,sizes:i,span:n,spellCheck:null,src:null,srcDoc:T,srcLang:null,srcSet:i,start:o,step:null,style:null,summary:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:T|N,width:i,wmode:i,wrap:null,about:i,datatype:i,inlist:i,prefix:i,property:i,resource:i,typeof:i,vocab:i,autoCapitalize:i,autoCorrect:i,autoSave:null,color:null,itemProp:i,itemScope:i|E,itemType:i,itemID:i,itemRef:i,results:null,security:i,unselectable:i},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoComplete:"autocomplete",autoFocus:"autofocus",autoPlay:"autoplay",autoSave:"autosave",encType:"encoding",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};A.exports=D},function(A,M,t){"use strict";var I=t(208),g=t(449),e=t(454),i=t(4),T=t(476),E={};i(E,e),i(E,{findDOMNode:T("findDOMNode","ReactDOM","react-dom",I,I.findDOMNode),render:T("render","ReactDOM","react-dom",I,I.render),unmountComponentAtNode:T("unmountComponentAtNode","ReactDOM","react-dom",I,I.unmountComponentAtNode),renderToString:T("renderToString","ReactDOMServer","react-dom/server",g,g.renderToString),renderToStaticMarkup:T("renderToStaticMarkup","ReactDOMServer","react-dom/server",g,g.renderToStaticMarkup)}),E.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=I,E.__SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=g,A.exports=E},function(A,M,t){"use strict";var I=(t(55),t(114)),g=(t(3),"_getDOMNodeDidWarn"),e={getDOMNode:function(){return this.constructor[g]=!0,I(this)}};A.exports=e},function(A,M,t){"use strict";function I(A,M,t){var I=void 0===A[t];null!=M&&I&&(A[t]=e(M,null))}var g=t(36),e=t(119),i=t(122),T=t(123),E=(t(3),{instantiateChildren:function(A,M,t){if(null==A)return null;var g={};return T(A,I,g),g},updateChildren:function(A,M,t,I){if(!M&&!A)return null;var T;for(T in M)if(M.hasOwnProperty(T)){var E=A&&A[T],N=E&&E._currentElement,o=M[T];if(null!=E&&i(N,o))g.receiveComponent(E,o,t,I),M[T]=E;else{E&&g.unmountComponent(E,T);var n=e(o,null);M[T]=n}}for(T in A)!A.hasOwnProperty(T)||M&&M.hasOwnProperty(T)||g.unmountComponent(A[T]);return M},unmountChildren:function(A){for(var M in A)if(A.hasOwnProperty(M)){var t=A[M];g.unmountComponent(t)}}});A.exports=E},function(A,M,t){"use strict";function I(A){var M=A._currentElement._owner||null;if(M){var t=M.getName();if(t)return" Check the render method of ` + "`" + `"+t+"` + "`" + `."}return""}function g(A){}var e=t(110),i=t(25),T=t(13),E=t(55),N=t(17),o=t(71),n=(t(70),t(36)),C=t(112),c=t(4),D=t(50),a=t(2),B=t(122);t(3);g.prototype.render=function(){var A=E.get(this)._currentElement.type;return A(this.props,this.context,this.updater)};var Q=1,r={construct:function(A){this._currentElement=A,this._rootNodeID=null,this._instance=null,this._pendingElement=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._renderedComponent=null,this._context=null,this._mountOrder=0,this._topLevelWrapper=null,this._pendingCallbacks=null},mountComponent:function(A,M,t){this._context=t,this._mountOrder=Q++,this._rootNodeID=A;var I,e,i=this._processProps(this._currentElement.props),N=this._processContext(t),o=this._currentElement.type,c="prototype"in o;c&&(I=new o(i,N,C)),c&&null!==I&&I!==!1&&!T.isValidElement(I)||(e=I,I=new g(o)),I.props=i,I.context=N,I.refs=D,I.updater=C,this._instance=I,E.set(I,this);var B=I.state;void 0===B&&(I.state=B=null),"object"!=typeof B||Array.isArray(B)?a(!1):void 0,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,I.componentWillMount&&(I.componentWillMount(),this._pendingStateQueue&&(I.state=this._processPendingState(I.props,I.context))),void 0===e&&(e=this._renderValidatedComponent()),this._renderedComponent=this._instantiateReactComponent(e);var r=n.mountComponent(this._renderedComponent,A,M,this._processChildContext(t));return I.componentDidMount&&M.getReactMountReady().enqueue(I.componentDidMount,I),r},unmountComponent:function(){var A=this._instance;A.componentWillUnmount&&A.componentWillUnmount(),n.unmountComponent(this._renderedComponent),this._renderedComponent=null,this._instance=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._pendingCallbacks=null,this._pendingElement=null,this._context=null,this._rootNodeID=null,this._topLevelWrapper=null,E.remove(A)},_maskContext:function(A){var M=null,t=this._currentElement.type,I=t.contextTypes;if(!I)return D;M={};for(var g in I)M[g]=A[g];return M},_processContext:function(A){var M=this._maskContext(A);return M},_processChildContext:function(A){var M=this._currentElement.type,t=this._instance,I=t.getChildContext&&t.getChildContext();if(I){"object"!=typeof M.childContextTypes?a(!1):void 0;for(var g in I)g in M.childContextTypes?void 0:a(!1);return c({},A,I)}return A},_processProps:function(A){return A},_checkPropTypes:function(A,M,t){var g=this.getName();for(var e in A)if(A.hasOwnProperty(e)){var i;try{"function"!=typeof A[e]?a(!1):void 0,i=A[e](M,e,g,t)}catch(A){i=A}if(i instanceof Error){I(this);t===o.prop}}},receiveComponent:function(A,M,t){var I=this._currentElement,g=this._context;this._pendingElement=null,this.updateComponent(M,I,A,g,t)},performUpdateIfNecessary:function(A){null!=this._pendingElement&&n.receiveComponent(this,this._pendingElement||this._currentElement,A,this._context),(null!==this._pendingStateQueue||this._pendingForceUpdate)&&this.updateComponent(A,this._currentElement,this._currentElement,this._context,this._context)},updateComponent:function(A,M,t,I,g){var e,i=this._instance,T=this._context===g?i.context:this._processContext(g);M===t?e=t.props:(e=this._processProps(t.props),i.componentWillReceiveProps&&i.componentWillReceiveProps(e,T));var E=this._processPendingState(e,T),N=this._pendingForceUpdate||!i.shouldComponentUpdate||i.shouldComponentUpdate(e,E,T);N?(this._pendingForceUpdate=!1,this._performComponentUpdate(t,e,E,T,A,g)):(this._currentElement=t,this._context=g,i.props=e,i.state=E,i.context=T)},_processPendingState:function(A,M){var t=this._instance,I=this._pendingStateQueue,g=this._pendingReplaceState;if(this._pendingReplaceState=!1,this._pendingStateQueue=null,!I)return t.state;if(g&&1===I.length)return I[0];for(var e=c({},g?I[0]:t.state),i=g?1:0;i=0||null!=M.is}function B(A){D(A),this._tag=A.toLowerCase(),this._renderedChildren=null,this._previousStyle=null,this._previousStyleCopy=null,this._rootNodeID=null,this._wrapperState=null,this._topLevelWrapper=null,this._nodeWithLegacyProperties=null}var Q=t(428),r=t(430),s=t(47),x=t(107),j=t(24),y=t(69),u=t(109),w=t(443),L=t(446),l=t(447),Y=t(210),d=t(450),h=t(12),S=t(455),z=t(17),U=t(112),p=t(4),O=t(74),m=t(75),F=t(2),f=(t(120),t(27)),k=t(76),R=t(121),J=(t(152),t(124),t(3),y.deleteListener),G=y.listenTo,H=y.registrationNameModules,b={string:!0,number:!0},X=f({children:null}),v=f({style:null}),W=f({__html:null}),V=1,P={topAbort:"abort",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topSeeked:"seeked",topSeeking:"seeking",topStalled:"stalled",topSuspend:"suspend",topTimeUpdate:"timeupdate",topVolumeChange:"volumechange",topWaiting:"waiting"},Z={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},K={listing:!0,pre:!0,textarea:!0},q=(p({menuitem:!0},Z),/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/),_={},$={}.hasOwnProperty;B.displayName="ReactDOMComponent",B.Mixin={construct:function(A){this._currentElement=A},mountComponent:function(A,M,t){this._rootNodeID=A;var I=this._currentElement.props;switch(this._tag){case"iframe":case"img":case"form":case"video":case"audio":this._wrapperState={listeners:null},M.getReactMountReady().enqueue(n,this);break;case"button":I=w.getNativeProps(this,I,t);break;case"input":L.mountWrapper(this,I,t),I=L.getNativeProps(this,I,t);break;case"option":l.mountWrapper(this,I,t),I=l.getNativeProps(this,I,t);break;case"select":Y.mountWrapper(this,I,t),I=Y.getNativeProps(this,I,t),t=Y.processChildContext(this,I,t);break;case"textarea":d.mountWrapper(this,I,t),I=d.getNativeProps(this,I,t)}E(this,I);var g;if(M.useCreateElement){var e=t[h.ownerDocumentContextKey],i=e.createElement(this._currentElement.type);x.setAttributeForID(i,this._rootNodeID),h.getID(i),this._updateDOMProperties({},I,M,i),this._createInitialChildren(M,I,t,i),g=i}else{var T=this._createOpenTagMarkupAndPutListeners(M,I),N=this._createContentMarkup(M,I,t);g=!N&&Z[this._tag]?T+"/>":T+">"+N+""}switch(this._tag){case"input":M.getReactMountReady().enqueue(C,this);case"button":case"select":case"textarea":I.autoFocus&&M.getReactMountReady().enqueue(Q.focusDOMComponent,this)}return g},_createOpenTagMarkupAndPutListeners:function(A,M){var t="<"+this._currentElement.type;for(var I in M)if(M.hasOwnProperty(I)){var g=M[I];if(null!=g)if(H.hasOwnProperty(I))g&&N(this._rootNodeID,I,g,A);else{I===v&&(g&&(g=this._previousStyleCopy=p({},M.style)),g=r.createMarkupForStyles(g));var e=null;null!=this._tag&&a(this._tag,M)?I!==X&&(e=x.createMarkupForCustomAttribute(I,g)):e=x.createMarkupForProperty(I,g),e&&(t+=" "+e)}}if(A.renderToStaticMarkup)return t;var i=x.createMarkupForID(this._rootNodeID);return t+" "+i},_createContentMarkup:function(A,M,t){var I="",g=M.dangerouslySetInnerHTML;if(null!=g)null!=g.__html&&(I=g.__html);else{var e=b[typeof M.children]?M.children:null,i=null!=e?null:M.children;if(null!=e)I=m(e);else if(null!=i){var T=this.mountChildren(i,A,t);I=T.join("")}}return K[this._tag]&&"\n"===I.charAt(0)?"\n"+I:I},_createInitialChildren:function(A,M,t,I){var g=M.dangerouslySetInnerHTML;if(null!=g)null!=g.__html&&k(I,g.__html);else{var e=b[typeof M.children]?M.children:null,i=null!=e?null:M.children;if(null!=e)R(I,e);else if(null!=i)for(var T=this.mountChildren(i,A,t),E=0;EM.end?(t=M.end,I=M.start):(t=M.start,I=M.end),g.moveToElementText(A),g.moveStart("character",t),g.setEndPoint("EndToStart",g),g.moveEnd("character",I-t),g.select()}function T(A,M){if(window.getSelection){var t=window.getSelection(),I=A[o()].length,g=Math.min(M.start,I),e="undefined"==typeof M.end?g:Math.min(M.end,I);if(!t.extend&&g>e){var i=e;e=g,g=i}var T=N(A,g),E=N(A,e);if(T&&E){var n=document.createRange();n.setStart(T.node,T.offset),t.removeAllRanges(),g>e?(t.addRange(n),t.extend(E.node,E.offset)):(n.setEnd(E.node,E.offset),t.addRange(n))}}}var E=t(10),N=t(479),o=t(228),n=E.canUseDOM&&"selection"in document&&!("getSelection"in window),C={getOffsets:n?g:e,setOffsets:n?i:T};A.exports=C},function(A,M,t){"use strict";var I=t(213),g=t(460),e=t(113);I.inject();var i={renderToString:g.renderToString,renderToStaticMarkup:g.renderToStaticMarkup,version:e};A.exports=i},function(A,M,t){"use strict";function I(){this._rootNodeID&&o.updateWrapper(this)}function g(A){var M=this._currentElement.props,t=e.executeOnChange(M,A);return T.asap(I,this),t}var e=t(108),i=t(111),T=t(18),E=t(4),N=t(2),o=(t(3),{getNativeProps:function(A,M,t){null!=M.dangerouslySetInnerHTML?N(!1):void 0;var I=E({},M,{defaultValue:void 0,value:void 0,children:A._wrapperState.initialValue,onChange:A._wrapperState.onChange});return I},mountWrapper:function(A,M){var t=M.defaultValue,I=M.children;null!=I&&(null!=t?N(!1):void 0,Array.isArray(I)&&(I.length<=1?void 0:N(!1),I=I[0]),t=""+I),null==t&&(t="");var i=e.getValue(M);A._wrapperState={initialValue:""+(null!=i?i:t),onChange:g.bind(A)}},updateWrapper:function(A){var M=A._currentElement.props,t=e.getValue(M);null!=t&&i.updatePropertyByID(A._rootNodeID,"value",""+t)}});A.exports=o},function(A,M,t){"use strict";function I(A){g.enqueueEvents(A),g.processEventQueue(!1)}var g=t(53),e={handleTopLevel:function(A,M,t,e,i){var T=g.extractEvents(A,M,t,e,i);I(T)}};A.exports=e},function(A,M,t){"use strict";function I(A){var M=C.getID(A),t=n.getReactRootIDFromNodeID(M),I=C.findReactContainerForID(t),g=C.getFirstReactDOM(I);return g}function g(A,M){this.topLevelType=A,this.nativeEvent=M,this.ancestors=[]}function e(A){i(A)}function i(A){for(var M=C.getFirstReactDOM(a(A.nativeEvent))||window,t=M;t;)A.ancestors.push(t),t=I(t);for(var g=0;g=M)return{node:g,offset:M-e};e=i}g=t(I(g))}}A.exports=g},function(A,M,t){"use strict";function I(A){return g.isValidElement(A)?void 0:e(!1),A}var g=t(13),e=t(2);A.exports=I},function(A,M,t){"use strict";function I(A){return'"'+g(A)+'"'}var g=t(75);A.exports=I},function(A,M,t){"use strict";var I=t(12);A.exports=I.renderSubtreeIntoContainer},function(A,M){A.exports=function(A,M,t){for(var I=0,g=A.length,e=3==arguments.length?t:A[I++];I=400){var T="cannot "+M.method+" "+M.url+" ("+i.status+")";A=new e(T),A.status=i.status,A.body=i.body,A.res=i,I(A)}else g?I(new e(g)):t(i)})})},g.prototype.then=function(){var A=this.promise();return A.then.apply(A,arguments)}},function(A,M,t){function I(){}function g(A){var M={}.toString.call(A);switch(M){case"[object File]":case"[object Blob]":case"[object FormData]":return!0;default:return!1}}function e(A){if(!s(A))return A;var M=[];for(var t in A)null!=A[t]&&i(M,t,A[t]);return M.join("&")}function i(A,M,t){return Array.isArray(t)?t.forEach(function(t){i(A,M,t)}):void A.push(encodeURIComponent(M)+"="+encodeURIComponent(t))}function T(A){for(var M,t,I={},g=A.split("&"),e=0,i=g.length;e=200&&M.status<300)return t.callback(A,M);var I=new Error(M.statusText||"Unsuccessful HTTP response");I.original=A,I.response=M,I.status=M.status,t.callback(I,M)})}function D(A,M){var t=x("DELETE",A);return M&&t.end(M),t}var a,B=t(273),Q=t(483),r=t(501),s=t(236);a="undefined"!=typeof window?window:"undefined"!=typeof self?self:this;var x=A.exports=t(502).bind(null,c);x.getXHR=function(){if(!(!a.XMLHttpRequest||a.location&&"file:"==a.location.protocol&&a.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(A){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(A){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(A){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(A){}return!1};var j="".trim?function(A){return A.trim()}:function(A){return A.replace(/(^\s*|\s*$)/g,"")};x.serializeObject=e,x.parseString=T,x.types={html:"text/html",json:"application/json",xml:"application/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},x.serialize={"application/x-www-form-urlencoded":e,"application/json":JSON.stringify},x.parse={"application/x-www-form-urlencoded":T,"application/json":JSON.parse},C.prototype.get=function(A){return this.header[A.toLowerCase()]},C.prototype.setHeaderProperties=function(A){var M=this.header["content-type"]||"";this.type=o(M);var t=n(M);for(var I in t)this[I]=t[I]},C.prototype.parseBody=function(A){ -var M=x.parse[this.type];return!M&&N(this.type)&&(M=x.parse["application/json"]),M&&A&&(A.length||A instanceof Object)?M(A):null},C.prototype.setStatusProperties=function(A){1223===A&&(A=204);var M=A/100|0;this.status=this.statusCode=A,this.statusType=M,this.info=1==M,this.ok=2==M,this.clientError=4==M,this.serverError=5==M,this.error=(4==M||5==M)&&this.toError(),this.accepted=202==A,this.noContent=204==A,this.badRequest=400==A,this.unauthorized=401==A,this.notAcceptable=406==A,this.notFound=404==A,this.forbidden=403==A},C.prototype.toError=function(){var A=this.req,M=A.method,t=A.url,I="cannot "+M+" "+t+" ("+this.status+")",g=new Error(I);return g.status=this.status,g.method=M,g.url=t,g},x.Response=C,B(c.prototype);for(var y in r)c.prototype[y]=r[y];c.prototype.abort=function(){if(!this.aborted)return this.aborted=!0,this.xhr&&this.xhr.abort(),this.clearTimeout(),this.emit("abort"),this},c.prototype.type=function(A){return this.set("Content-Type",x.types[A]||A),this},c.prototype.responseType=function(A){return this._responseType=A,this},c.prototype.accept=function(A){return this.set("Accept",x.types[A]||A),this},c.prototype.auth=function(A,M,t){switch(t||(t={type:"basic"}),t.type){case"basic":var I=btoa(A+":"+M);this.set("Authorization","Basic "+I);break;case"auto":this.username=A,this.password=M}return this},c.prototype.query=function(A){return"string"!=typeof A&&(A=e(A)),A&&this._query.push(A),this},c.prototype.attach=function(A,M,t){return this._getFormData().append(A,M,t||M.name),this},c.prototype._getFormData=function(){return this._formData||(this._formData=new a.FormData),this._formData},c.prototype.send=function(A){var M=s(A),t=this._header["content-type"];if(M&&s(this._data))for(var I in A)this._data[I]=A[I];else"string"==typeof A?(t||this.type("form"),t=this._header["content-type"],"application/x-www-form-urlencoded"==t?this._data=this._data?this._data+"&"+A:A:this._data=(this._data||"")+A):this._data=A;return!M||g(A)?this:(t||this.type("json"),this)},C.prototype.parse=function(A){return a.console&&console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0"),this.serialize(A),this},C.prototype.serialize=function(A){return this._parser=A,this},c.prototype.callback=function(A,M){var t=this._callback;this.clearTimeout(),t(A,M)},c.prototype.crossDomainError=function(){var A=new Error("Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.");A.crossDomain=!0,A.status=this.status,A.method=this.method,A.url=this.url,this.callback(A)},c.prototype.timeoutError=function(){var A=this._timeout,M=new Error("timeout of "+A+"ms exceeded");M.timeout=A,this.callback(M)},c.prototype.withCredentials=function(){return this._withCredentials=!0,this},c.prototype.end=function(A){var M=this,t=this.xhr=x.getXHR(),e=this._query.join("&"),i=this._timeout,T=this._formData||this._data;this._callback=A||I,t.onreadystatechange=function(){if(4==t.readyState){var A;try{A=t.status}catch(M){A=0}if(0==A){if(M.timedout)return M.timeoutError();if(M.aborted)return;return M.crossDomainError()}M.emit("end")}};var E=function(A){A.total>0&&(A.percent=A.loaded/A.total*100),A.direction="download",M.emit("progress",A)};this.hasListeners("progress")&&(t.onprogress=E);try{t.upload&&this.hasListeners("progress")&&(t.upload.onprogress=E)}catch(A){}if(i&&!this._timer&&(this._timer=setTimeout(function(){M.timedout=!0,M.abort()},i)),e&&(e=x.serializeObject(e),this.url+=~this.url.indexOf("?")?"&"+e:"?"+e),this.username&&this.password?t.open(this.method,this.url,!0,this.username,this.password):t.open(this.method,this.url,!0),this._withCredentials&&(t.withCredentials=!0),"GET"!=this.method&&"HEAD"!=this.method&&"string"!=typeof T&&!g(T)){var o=this._header["content-type"],n=this._parser||x.serialize[o?o.split(";")[0]:""];!n&&N(o)&&(n=x.serialize["application/json"]),n&&(T=n(T))}for(var C in this.header)null!=this.header[C]&&t.setRequestHeader(C,this.header[C]);return this._responseType&&(t.responseType=this._responseType),this.emit("request",this),t.send("undefined"!=typeof T?T:null),this},x.Request=c,x.get=function(A,M,t){var I=x("GET",A);return"function"==typeof M&&(t=M,M=null),M&&I.query(M),t&&I.end(t),I},x.head=function(A,M,t){var I=x("HEAD",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I},x.del=D,x.delete=D,x.patch=function(A,M,t){var I=x("PATCH",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I},x.post=function(A,M,t){var I=x("POST",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I},x.put=function(A,M,t){var I=x("PUT",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I}},function(A,M,t){var I=t(236);M.clearTimeout=function(){return this._timeout=0,clearTimeout(this._timer),this},M.parse=function(A){return this._parser=A,this},M.timeout=function(A){return this._timeout=A,this},M.then=function(A,M){return this.end(function(t,I){t?M(t):A(I)})},M.use=function(A){return A(this),this},M.get=function(A){return this._header[A.toLowerCase()]},M.getHeader=M.get,M.set=function(A,M){if(I(A)){for(var t in A)this.set(t,A[t]);return this}return this._header[A.toLowerCase()]=M,this.header[A]=M,this},M.unset=function(A){return delete this._header[A.toLowerCase()],delete this.header[A],this},M.field=function(A,M){return this._getFormData().append(A,M),this}},function(A,M){function t(A,M,t){return"function"==typeof t?new A("GET",M).end(t):2==arguments.length?new A("GET",M):new A(M,t)}A.exports=t},function(A,M,t){A.exports=t(504)},function(A,M,t){(function(A,I){"use strict";function g(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var e,i=t(505),T=g(i);e="undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof A?A:I;var E=(0,T.default)(e);M.default=E}).call(M,function(){return this}(),t(128)(A))},function(A,M){"use strict";function t(A){var M,t=A.Symbol;return"function"==typeof t?t.observable?M=t.observable:(M=t("observable"),t.observable=M):M="@@observable",M}Object.defineProperty(M,"__esModule",{value:!0}),M.default=t},function(A,M,t){function I(A){return g(A).replace(/\s(\w)/g,function(A,M){return M.toUpperCase()})}var g=t(508);A.exports=I},function(A,M){function t(A){return e.test(A)?A.toLowerCase():i.test(A)?(I(A)||A).toLowerCase():T.test(A)?g(A).toLowerCase():A.toLowerCase()}function I(A){return A.replace(E,function(A,M){return M?" "+M:""})}function g(A){return A.replace(N,function(A,M,t){return M+" "+t.toLowerCase().split("").join(" ")})}A.exports=t;var e=/\s/,i=/(_|-|\.|:)/,T=/([a-z][A-Z]|[A-Z][a-z])/,E=/[\W_]+(.|$)/g,N=/(.)([A-Z]+)/g},function(A,M,t){function I(A){return g(A).replace(/[\W_]+(.|$)/g,function(A,M){return M?" "+M:""}).trim()}var g=t(507);A.exports=I},function(A,M){A.exports=function(){var A=document.getSelection();if(!A.rangeCount)return function(){};for(var M=document.activeElement,t=[],I=0;I=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function i(A,M){function t(I,g){function i(A,t){var I=c.getLinkName(A),e=this.props[g[A]];I&&E(this.props,I)&&!e&&(e=this.props[I].requestChange);for(var i=arguments.length,T=Array(i>2?i-2:0),N=2;N=15||0===s[0]&&s[1]>=13?A:A.type}function T(A,M){var t=N(M);return t&&!E(A,M)&&E(A,t)?A[t].value:A[M]}function E(A,M){return void 0!==A[M]}function N(A){return"value"===A?"valueLink":"checked"===A?"checkedLink":null}function o(A){return"default"+A.charAt(0).toUpperCase()+A.substr(1)}function n(A,M,t){return function(){for(var I=arguments.length,g=Array(I),e=0;eo||N===o&&"application/"===M[T].substr(0,12))continue}M[T]=I}}})}var E=t(351),N=t(354).extname,o=/^\s*([^;\s]*)(?:;|\s|$)/,n=/^text\//i;M.charset=I,M.charsets={lookup:I},M.contentType=g,M.extension=e,M.extensions=Object.create(null),M.lookup=i,M.types=Object.create(null),T(M.extensions,M.types)},function(A,M){function t(A){throw new Error("Cannot find module '"+A+"'.")}t.keys=function(){return[]},t.resolve=t,A.exports=t,t.id=353},function(A,M,t){(function(A){function t(A,M){for(var t=0,I=A.length-1;I>=0;I--){var g=A[I];"."===g?A.splice(I,1):".."===g?(A.splice(I,1),t++):t&&(A.splice(I,1),t--)}if(M)for(;t--;t)A.unshift("..");return A}function I(A,M){if(A.filter)return A.filter(M);for(var t=[],I=0;I=-1&&!g;e--){var i=e>=0?arguments[e]:A.cwd();if("string"!=typeof i)throw new TypeError("Arguments to path.resolve must be strings");i&&(M=i+"/"+M,g="/"===i.charAt(0))}return M=t(I(M.split("/"),function(A){return!!A}),!g).join("/"),(g?"/":"")+M||"."},M.normalize=function(A){var g=M.isAbsolute(A),e="/"===i(A,-1);return A=t(I(A.split("/"),function(A){return!!A}),!g).join("/"),A||g||(A="."),A&&e&&(A+="/"),(g?"/":"")+A},M.isAbsolute=function(A){return"/"===A.charAt(0)},M.join=function(){var A=Array.prototype.slice.call(arguments,0);return M.normalize(I(A,function(A,M){if("string"!=typeof A)throw new TypeError("Arguments to path.join must be strings");return A}).join("/"))},M.relative=function(A,t){function I(A){for(var M=0;M=0&&""===A[t];t--);return M>t?[]:A.slice(M,t-M+1)}A=M.resolve(A).substr(1),t=M.resolve(t).substr(1);for(var g=I(A.split("/")),e=I(t.split("/")),i=Math.min(g.length,e.length),T=i,E=0;E=0;e--){var i=I[e]+g;if(i in M)return i}return!1}},function(A,M,t){"use strict";var I=t(497);M.extract=function(A){return A.split("?")[1]||""},M.parse=function(A){return"string"!=typeof A?{}:(A=A.trim().replace(/^(\?|#|&)/,""),A?A.split("&").reduce(function(A,M){var t=M.replace(/\+/g," ").split("="),I=t.shift(),g=t.length>0?t.join("="):void 0;return I=decodeURIComponent(I),g=void 0===g?null:decodeURIComponent(g),A.hasOwnProperty(I)?Array.isArray(A[I])?A[I].push(g):A[I]=[A[I],g]:A[I]=g,A},{}):{})},M.stringify=function(A){return A?Object.keys(A).sort().map(function(M){var t=A[M];return void 0===t?"":null===t?M:Array.isArray(t)?t.slice().sort().map(function(A){return I(M)+"="+I(A)}).join("&"):I(M)+"="+I(t)}).filter(function(A){return A.length>0}).join("&"):""}},function(A,M){"use strict";function t(A,M){return Object.prototype.hasOwnProperty.call(A,M)}A.exports=function(A,M,I,g){M=M||"&",I=I||"=";var e={};if("string"!=typeof A||0===A.length)return e;var i=/\+/g;A=A.split(M);var T=1e3;g&&"number"==typeof g.maxKeys&&(T=g.maxKeys);var E=A.length;T>0&&E>T&&(E=T);for(var N=0;N=0?(o=D.substr(0,a),n=D.substr(a+1)):(o=D,n=""),C=decodeURIComponent(o),c=decodeURIComponent(n),t(e,C)?Array.isArray(e[C])?e[C].push(c):e[C]=[e[C],c]:e[C]=c}return e}},function(A,M){"use strict";var t=function(A){switch(typeof A){case"string":return A;case"boolean":return A?"true":"false";case"number":return isFinite(A)?A:"";default:return""}};A.exports=function(A,M,I,g){return M=M||"&",I=I||"=",null===A&&(A=void 0),"object"==typeof A?Object.keys(A).map(function(g){var e=encodeURIComponent(t(g))+I;return Array.isArray(A[g])?A[g].map(function(A){return e+encodeURIComponent(t(A))}).join(M):e+encodeURIComponent(t(A[g]))}).join(M):g?encodeURIComponent(t(g))+I+encodeURIComponent(t(A)):""}},function(A,M,t){"use strict";M.decode=M.parse=t(358),M.encode=M.stringify=t(359)},function(A,M,t){(function(M){for(var I=t(355),g="undefined"==typeof window?M:window,e=["moz","webkit"],i="AnimationFrame",T=g["request"+i],E=g["cancel"+i]||g["cancelRequest"+i],N=0;!T&&N1)||(e=A,!1)}),e)return new Error("(children) "+I+" - Duplicate children detected of bsRole: "+e+". Only one child each allowed with the following bsRoles: "+M.join(", "))})}},A.exports=M.default},function(A,M,t){"use strict";function I(A){var M=[];return void 0===A?M:(i.default.forEach(A,function(A){M.push(A)}),M)}var g=t(6).default;M.__esModule=!0,M.default=I;var e=t(51),i=g(e);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}Object.defineProperty(M,"__esModule",{value:!0}),M.CopyToClipboard=void 0;var e=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){var M=A.style,t=g(A,["style"]),I=o({},M,{height:6,right:2,bottom:2,left:2,borderRadius:3});return C.default.createElement("div",o({style:I},t))}function i(A){var M=A.style,t=g(A,["style"]),I=o({},M,{width:6,right:2,bottom:2,top:2,borderRadius:3});return C.default.createElement("div",o({style:I},t))}function T(A){var M=A.style,t=g(A,["style"]),I=o({},M,{cursor:"pointer",borderRadius:"inherit",backgroundColor:"rgba(0,0,0,.2)"});return C.default.createElement("div",o({style:I},t))}function E(A){var M=A.style,t=g(A,["style"]),I=o({},M,{cursor:"pointer",borderRadius:"inherit",backgroundColor:"rgba(0,0,0,.2)"});return C.default.createElement("div",o({style:I},t))}function N(A){return C.default.createElement("div",A)}var o=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}var e=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=Object.assign||function(A){for(var M=1;M0||(this.setState({isDragActive:!1,isDragReject:!1}),this.props.onDragLeave&&this.props.onDragLeave.call(this,A))}},{key:"onDrop",value:function A(M){var t=this,I=this.props,A=I.onDrop,g=I.onDropAccepted,e=I.onDropRejected,i=I.multiple,T=I.disablePreview,E=(0,a.default)(M,i),N=[],o=[];M.preventDefault(),this.enterCounter=0,this.isFileDialogActive=!1,E.forEach(function(A){T||(A.preview=window.URL.createObjectURL(A)),t.fileAccepted(A)&&t.fileMatchSize(A)?N.push(A):o.push(A)}),A&&A.call(this,N,o,M),o.length>0&&e&&e.call(this,o,M),N.length>0&&g&&g.call(this,N,M),this.setState({isDragActive:!1,isDragReject:!1})}},{key:"onClick",value:function A(M){M.stopPropagation();var t=this.props,A=t.onClick,I=t.disableClick;I||(this.open(),A&&A.call(this,M))}},{key:"onFileDialogCancel",value:function A(){var A=this.props.onFileDialogCancel,M=this.fileInputEl,t=this.isFileDialogActive;A&&t&&setTimeout(function(){var I=M.files;I.length||(t=!1,A())},300)}},{key:"fileAccepted",value:function(A){return(0,c.default)(A,this.props.accept)}},{key:"fileMatchSize",value:function(A){return A.size<=this.props.maxSize&&A.size>=this.props.minSize}},{key:"allFilesAccepted",value:function(A){return A.every(this.fileAccepted)}},{key:"open",value:function(){this.isFileDialogActive=!0,this.fileInputEl.value=null,this.fileInputEl.click()}},{key:"render",value:function(){var A=this,M=this.props,t=M.accept,I=M.activeClassName,e=M.inputProps,i=M.multiple,T=M.name,N=M.rejectClassName,o=g(M,["accept","activeClassName","inputProps","multiple","name","rejectClassName"]),C=o.activeStyle,c=o.className,D=o.rejectStyle,a=o.style,Q=g(o,["activeStyle","className","rejectStyle","style"]),r=this.state,s=r.isDragActive,x=r.isDragReject;c=c||"",s&&I&&(c+=" "+I),x&&N&&(c+=" "+N),c||a||C||D||(a={width:200,height:200,borderWidth:2,borderColor:"#666",borderStyle:"dashed",borderRadius:5},C={borderStyle:"solid",backgroundColor:"#eee"},D={borderStyle:"solid",backgroundColor:"#ffdddd"});var j=void 0;j=C&&s?E({},a,C):D&&x?E({},a,D):E({},a);var y={accept:t,type:"file",style:{display:"none"},multiple:B&&i,ref:function(M){return A.fileInputEl=M},onChange:this.onDrop};T&&T.length&&(y.name=T);var u=["acceptedFiles","disablePreview","disableClick","onDropAccepted","onDropRejected","onFileDialogCancel","maxSize","minSize"],w=E({},Q);return u.forEach(function(A){return delete w[A]}),n.default.createElement("div",E({className:c,style:j},w,{onClick:this.onClick,onDragStart:this.onDragStart,onDragEnter:this.onDragEnter,onDragOver:this.onDragOver,onDragLeave:this.onDragLeave,onDrop:this.onDrop}),this.props.children,n.default.createElement("input",E({},e,y)))}}]),M}(n.default.Component);Q.defaultProps={disablePreview:!1,disableClick:!1,multiple:!0,maxSize:1/0,minSize:0},Q.propTypes={onClick:n.default.PropTypes.func,onDrop:n.default.PropTypes.func,onDropAccepted:n.default.PropTypes.func,onDropRejected:n.default.PropTypes.func,onDragStart:n.default.PropTypes.func,onDragEnter:n.default.PropTypes.func,onDragOver:n.default.PropTypes.func,onDragLeave:n.default.PropTypes.func,children:n.default.PropTypes.node,style:n.default.PropTypes.object,activeStyle:n.default.PropTypes.object,rejectStyle:n.default.PropTypes.object,className:n.default.PropTypes.string,activeClassName:n.default.PropTypes.string,rejectClassName:n.default.PropTypes.string,disablePreview:n.default.PropTypes.bool,disableClick:n.default.PropTypes.bool,onFileDialogCancel:n.default.PropTypes.func,inputProps:n.default.PropTypes.object,multiple:n.default.PropTypes.bool,accept:n.default.PropTypes.string,name:n.default.PropTypes.string,maxSize:n.default.PropTypes.number,minSize:n.default.PropTypes.number},M.default=Q,A.exports=M.default},function(M,t){M.exports=A},function(A,M){A.exports=function(A){function M(I){if(t[I])return t[I].exports;var g=t[I]={exports:{},id:I,loaded:!1};return A[I].call(g.exports,g,g.exports,M),g.loaded=!0,g.exports}var t={};return M.m=A,M.c=t,M.p="",M(0)}([function(A,M,t){"use strict";M.__esModule=!0,t(8),t(9),M.default=function(A,M){if(A&&M){var t=function(){var t=Array.isArray(M)?M:M.split(","),I=A.name||"",g=A.type||"",e=g.replace(/\/.*$/,"");return{v:t.some(function(A){var M=A.trim();return"."===M.charAt(0)?I.toLowerCase().endsWith(M.toLowerCase()):/\/\*$/.test(M)?e===M.replace(/\/.*$/,""):g===M})}}();if("object"==typeof t)return t.v}return!0},A.exports=M.default},function(A,M){var t=A.exports={version:"1.2.2"};"number"==typeof __e&&(__e=t)},function(A,M){var t=A.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},function(A,M,t){var I=t(2),g=t(1),e=t(4),i=t(19),T="prototype",E=function(A,M){return function(){return A.apply(M,arguments)}},N=function(A,M,t){var o,n,C,c,D=A&N.G,a=A&N.P,B=D?I:A&N.S?I[M]||(I[M]={}):(I[M]||{})[T],Q=D?g:g[M]||(g[M]={});D&&(t=M);for(o in t)n=!(A&N.F)&&B&&o in B,C=(n?B:t)[o],c=A&N.B&&n?E(C,I):a&&"function"==typeof C?E(Function.call,C):C,B&&!n&&i(B,o,C),Q[o]!=C&&e(Q,o,c),a&&((Q[T]||(Q[T]={}))[o]=C)};I.core=g,N.F=1,N.G=2,N.S=4,N.P=8,N.B=16,N.W=32,A.exports=N},function(A,M,t){var I=t(5),g=t(18);A.exports=t(22)?function(A,M,t){return I.setDesc(A,M,g(1,t))}:function(A,M,t){return A[M]=t,A}},function(A,M){var t=Object;A.exports={create:t.create,getProto:t.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:t.getOwnPropertyDescriptor,setDesc:t.defineProperty,setDescs:t.defineProperties,getKeys:t.keys,getNames:t.getOwnPropertyNames,getSymbols:t.getOwnPropertySymbols,each:[].forEach}},function(A,M){var t=0,I=Math.random();A.exports=function(A){return"Symbol(".concat(void 0===A?"":A,")_",(++t+I).toString(36))}},function(A,M,t){var I=t(20)("wks"),g=t(2).Symbol;A.exports=function(A){return I[A]||(I[A]=g&&g[A]||(g||t(6))("Symbol."+A))}},function(A,M,t){t(26),A.exports=t(1).Array.some},function(A,M,t){t(25),A.exports=t(1).String.endsWith},function(A,M){A.exports=function(A){if("function"!=typeof A)throw TypeError(A+" is not a function!");return A}},function(A,M){var t={}.toString;A.exports=function(A){return t.call(A).slice(8,-1)}},function(A,M,t){var I=t(10);A.exports=function(A,M,t){if(I(A),void 0===M)return A;switch(t){case 1:return function(t){return A.call(M,t)};case 2:return function(t,I){return A.call(M,t,I)};case 3:return function(t,I,g){return A.call(M,t,I,g)}}return function(){return A.apply(M,arguments)}}},function(A,M){A.exports=function(A){if(void 0==A)throw TypeError("Can't call method on "+A);return A}},function(A,M,t){A.exports=function(A){var M=/./;try{"/./"[A](M)}catch(I){try{return M[t(7)("match")]=!1,!"/./"[A](M)}catch(A){}}return!0}},function(A,M){A.exports=function(A){try{return!!A()}catch(A){return!0}}},function(A,M){A.exports=function(A){return"object"==typeof A?null!==A:"function"==typeof A}},function(A,M,t){var I=t(16),g=t(11),e=t(7)("match");A.exports=function(A){var M;return I(A)&&(void 0!==(M=A[e])?!!M:"RegExp"==g(A))}},function(A,M){A.exports=function(A,M){return{enumerable:!(1&A),configurable:!(2&A),writable:!(4&A),value:M}}},function(A,M,t){var I=t(2),g=t(4),e=t(6)("src"),i="toString",T=Function[i],E=(""+T).split(i);t(1).inspectSource=function(A){return T.call(A)},(A.exports=function(A,M,t,i){"function"==typeof t&&(g(t,e,A[M]?""+A[M]:E.join(String(M))),"name"in t||(t.name=M)),A===I?A[M]=t:(i||delete A[M],g(A,M,t))})(Function.prototype,i,function(){return"function"==typeof this&&this[e]||T.call(this)})},function(A,M,t){var I=t(2),g="__core-js_shared__",e=I[g]||(I[g]={});A.exports=function(A){return e[A]||(e[A]={})}},function(A,M,t){var I=t(17),g=t(13);A.exports=function(A,M,t){if(I(M))throw TypeError("String#"+t+" doesn't accept regex!");return String(g(A))}},function(A,M,t){A.exports=!t(15)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(A,M){var t=Math.ceil,I=Math.floor;A.exports=function(A){return isNaN(A=+A)?0:(A>0?I:t)(A)}},function(A,M,t){var I=t(23),g=Math.min;A.exports=function(A){return A>0?g(I(A),9007199254740991):0}},function(A,M,t){"use strict";var I=t(3),g=t(24),e=t(21),i="endsWith",T=""[i];I(I.P+I.F*t(14)(i),"String",{endsWith:function(A){var M=e(this,A,i),t=arguments,I=t.length>1?t[1]:void 0,E=g(M.length),N=void 0===I?E:Math.min(g(I),E),o=String(A);return T?T.call(M,o,N):M.slice(N-o.length,N)===o}})},function(A,M,t){var I=t(5),g=t(3),e=t(1).Array||Array,i={},T=function(A,M){I.each.call(A.split(","),function(A){void 0==M&&A in e?i[A]=e[A]:A in[]&&(i[A]=t(12)(Function.call,[][A],M))})};T("pop,reverse,shift,keys,values,entries",1),T("indexOf,every,some,forEach,map,filter,find,findIndex,includes",3),T("join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill"),g(g.S,"Array",i)}])},function(A,M){"use strict";function t(A){var M=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],t=[];if(A.dataTransfer){var I=A.dataTransfer;I.files&&I.files.length?t=I.files:I.items&&I.items.length&&(t=I.items)}else A.target&&A.target.files&&(t=A.target.files);return t.length>0&&(t=M?t:[t[0]]),Array.prototype.slice.call(t)}Object.defineProperty(M,"__esModule",{value:!0}),M.default=t,A.exports=M.default}])})},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=function(){function A(A,M){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:{},t=M.hideSiblingNodes,I=void 0===t||t,e=M.handleContainerOverflow,i=void 0===e||e;g(this,A),this.hideSiblingNodes=I,this.handleContainerOverflow=i,this.modals=[],this.containers=[],this.data=[]}return N(A,[{key:"add",value:function(A,M,t){var I=this.modals.indexOf(A),g=this.containers.indexOf(M);if(I!==-1)return I;if(I=this.modals.length,this.modals.push(A),this.hideSiblingNodes&&(0,r.hideSiblings)(M,A.mountNode),g!==-1)return this.data[g].modals.push(A),I;var e={modals:[A],classes:t?t.split(/\s+/):[],overflowing:(0,Q.default)(M)};return this.handleContainerOverflow&&T(e,M),e.classes.forEach(c.default.addClass.bind(null,M)),this.containers.push(M),this.data.push(e),I}},{key:"remove",value:function(A){var M=this.modals.indexOf(A);if(M!==-1){var t=i(this.data,A),I=this.data[t],g=this.containers[t];I.modals.splice(I.modals.indexOf(A),1),this.modals.splice(M,1),0===I.modals.length?(I.classes.forEach(c.default.removeClass.bind(null,g)),this.handleContainerOverflow&&E(I,g),this.hideSiblingNodes&&(0,r.showSiblings)(g,A.mountNode),this.containers.splice(t,1),this.data.splice(t,1)):this.hideSiblingNodes&&(0,r.ariaHidden)(!1,I.modals[I.modals.length-1].mountNode)}}},{key:"isTopModal",value:function(A){return!!this.modals.length&&this.modals[this.modals.length-1]===A}}]),A}();M.default=s,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=Object.assign||function(A){for(var M=1;M1?t-1:0),g=1;g=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}Object.defineProperty(M,"__esModule",{value:!0});var E=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function i(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function T(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}function E(){}Object.defineProperty(M,"__esModule",{value:!0}),M.EXITING=M.ENTERED=M.ENTERING=M.EXITED=M.UNMOUNTED=void 0;var N=Object.assign||function(A){for(var M=1;MT?T-N:0}function i(A,M,t,I){var e=g(t),i=e.width,T=A-I,E=A+I+M;return T<0?-T:E>i?i-E:0}function T(A,M,t,I,g){var T="BODY"===I.tagName?(0,N.default)(t):(0,n.default)(t,I),E=(0,N.default)(M),o=E.height,C=E.width,c=void 0,D=void 0,a=void 0,B=void 0;if("left"===A||"right"===A){D=T.top+(T.height-o)/2,c="left"===A?T.left-C:T.left+T.width;var Q=e(D,o,I,g);D+=Q,B=50*(1-2*Q/o)+"%",a=void 0}else{if("top"!==A&&"bottom"!==A)throw new Error('calcOverlayPosition(): No such placement of "'+A+'" found.');c=T.left+(T.width-C)/2,D="top"===A?T.top-o:T.top+T.height;var r=i(c,C,I,g);c+=r,a=50*(1-2*r/C)+"%",B=void 0}return{positionLeft:c,positionTop:D,arrowOffsetLeft:a,arrowOffsetTop:B}}Object.defineProperty(M,"__esModule",{value:!0}),M.default=T;var E=t(143),N=I(E),o=t(287),n=I(o),C=t(144),c=I(C),D=t(52),a=I(D);A.exports=M.default},function(A,M){"use strict";function t(A,M){M&&(A?M.setAttribute("aria-hidden","true"):M.removeAttribute("aria-hidden"))}function I(A,M){T(A,M,function(A){return t(!0,A)})}function g(A,M){T(A,M,function(A){return t(!1,A)})}Object.defineProperty(M,"__esModule",{value:!0}),M.ariaHidden=t,M.hideSiblings=I,M.showSiblings=g;var e=["template","script","style"],i=function(A){var M=A.nodeType,t=A.tagName;return 1===M&&e.indexOf(t.toLowerCase())===-1},T=function(A,M,t){M=[].concat(M),[].forEach.call(A.children,function(A){M.indexOf(A)===-1&&i(A)&&t(A)})}},function(A,M,t){"use strict";var I=function(){};A.exports=I},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){return function(t,I,g){if(null!=t[I]){var e='"'+I+'" property of "'+g+'" has been deprecated.\n'+M;E[e]||(T.default(!1,e),E[e]=!0)}return A(t,I,g)}}function e(){E={}}M.__esModule=!0,M.default=g;var i=t(127),T=I(i),E={};g._resetWarned=e,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}function e(A,M){if(!A)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!M||"object"!=typeof M&&"function"!=typeof M?A:M}function i(A,M){if("function"!=typeof M&&null!==M)throw new TypeError("Super expression must either be null or a function, not "+typeof M);A.prototype=Object.create(M&&M.prototype,{constructor:{value:A,enumerable:!1,writable:!0,configurable:!0}}),M&&(Object.setPrototypeOf?Object.setPrototypeOf(A,M):A.__proto__=M)}M.__esModule=!0,M.default=void 0;var T=t(1),E=t(184),N=I(E),o=t(185),n=(I(o),function(A){function M(t,I){g(this,M);var i=e(this,A.call(this,t,I));return i.store=t.store,i}return i(M,A),M.prototype.getChildContext=function(){return{store:this.store}},M.prototype.render=function(){return T.Children.only(this.props.children)},M}(T.Component));M.default=n,n.propTypes={store:N.default.isRequired,children:T.PropTypes.element.isRequired},n.childContextTypes={store:N.default.isRequired}},function(A,M){"use strict";function t(A,M){if(A===M)return!0;var t=Object.keys(A),I=Object.keys(M);if(t.length!==I.length)return!1;for(var g=Object.prototype.hasOwnProperty,e=0;e=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A,M){var t=A.history,I=A.routes,e=A.location,E=g(A,["history","routes","location"]);t||e?void 0:(0,N.default)(!1),t=t?t:(0,n.default)(E);var o=(0,c.default)(t,(0,D.createRoutes)(I)),C=void 0;e?e=t.createLocation(e):C=t.listen(function(A){e=A});var B=(0,a.createRouterObject)(t,o);t=(0,a.createRoutingHistory)(t,o),o.match(e,function(A,I,g){M(A,I&&B.createLocation(I,T.REPLACE),g&&i({},g,{history:t,router:B,matchContext:{history:t,transitionManager:o,router:B}})),C&&C()})}M.__esModule=!0;var i=Object.assign||function(A){for(var M=1;M=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return function(){var M=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],t=M.routes,I=g(M,["routes"]),e=(0,E.default)(A)(I),T=(0,o.default)(e,t);return i({},e,T)}}M.__esModule=!0;var i=Object.assign||function(A){for(var M=1;M=A&&N&&(T=!0,t()))}}var i=0,T=!1,E=!1,N=!1,o=void 0;e()}M.__esModule=!0;var I=Array.prototype.slice;M.loopAsync=t},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(){function A(A){try{A=A||window.history.state||{}}catch(M){A={}}var M=n.getWindowPath(),t=A,I=t.key,g=void 0;I?g=C.readState(I):(g=null,I=s.createKey(),Q&&window.history.replaceState(e({},A,{key:I}),null));var i=N.parsePath(M);return s.createLocation(e({},i,{state:g}),void 0,I)}function M(M){function t(M){void 0!==M.state&&I(A(M.state))}var I=M.transitionTo;return n.addEventListener(window,"popstate",t),function(){n.removeEventListener(window,"popstate",t)}}function t(A){var M=A.basename,t=A.pathname,I=A.search,g=A.hash,e=A.state,i=A.action,T=A.key;if(i!==E.POP){C.saveState(T,e);var N=(M||"")+t+I+g,o={key:T};if(i===E.PUSH){if(r)return window.location.href=N,!1;window.history.pushState(o,null,N)}else{if(r)return window.location.replace(N),!1;window.history.replaceState(o,null,N)}}}function I(A){1===++x&&(j=M(s));var t=s.listenBefore(A);return function(){t(),0===--x&&j()}}function g(A){1===++x&&(j=M(s));var t=s.listen(A);return function(){t(),0===--x&&j()}}function i(A){1===++x&&(j=M(s)),s.registerTransitionHook(A)}function c(A){s.unregisterTransitionHook(A),0===--x&&j()}var a=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];o.canUseDOM?void 0:T.default(!1);var B=a.forceRefresh,Q=n.supportsHistory(),r=!Q||B,s=D.default(e({},a,{getCurrentLocation:A,finishTransition:t,saveState:C.saveState})),x=0,j=void 0;return e({},s,{listenBefore:I,listen:g,registerTransitionHook:i,unregisterTransitionHook:c})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M=0&&M=0&&B8&&u<=11),l=32,Y=String.fromCharCode(l),d=c.topLevelTypes,h={beforeInput:{phasedRegistrationNames:{bubbled:s({onBeforeInput:null}),captured:s({onBeforeInputCapture:null})},dependencies:[d.topCompositionEnd,d.topKeyPress,d.topTextInput,d.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:s({onCompositionEnd:null}),captured:s({onCompositionEndCapture:null})},dependencies:[d.topBlur,d.topCompositionEnd,d.topKeyDown,d.topKeyPress,d.topKeyUp,d.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:s({onCompositionStart:null}),captured:s({onCompositionStartCapture:null})},dependencies:[d.topBlur,d.topCompositionStart,d.topKeyDown,d.topKeyPress,d.topKeyUp,d.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:s({onCompositionUpdate:null}),captured:s({onCompositionUpdateCapture:null})},dependencies:[d.topBlur,d.topCompositionUpdate,d.topKeyDown,d.topKeyPress,d.topKeyUp,d.topMouseDown]}},S=!1,z=null,p={eventTypes:h,extractEvents:function(A,M,t,I,g){return[N(A,M,t,I,g),C(A,M,t,I,g)]}};A.exports=p},function(A,M,t){"use strict";var I=t(202),g=t(10),e=t(17),i=(t(297),t(476)),T=t(302),E=t(306),N=(t(3),E(function(A){return T(A)})),o=!1,n="cssFloat";if(g.canUseDOM){var C=document.createElement("div").style;try{C.font=""}catch(A){o=!0}void 0===document.documentElement.style.cssFloat&&(n="styleFloat")}var c={createMarkupForStyles:function(A){var M="";for(var t in A)if(A.hasOwnProperty(t)){var I=A[t];null!=I&&(M+=N(t)+":",M+=i(t,I)+";")}return M||null},setValueForStyles:function(A,M){var t=A.style;for(var g in M)if(M.hasOwnProperty(g)){var e=i(g,M[g]);if("float"===g&&(g=n),e)t[g]=e;else{var T=o&&I.shorthandPropertyExpansions[g];if(T)for(var E in T)t[E]="";else t[g]=""}}}};e.measureMethods(c,"CSSPropertyOperations",{setValueForStyles:"setValueForStyles"}),A.exports=c},function(A,M,t){"use strict";function I(A){var M=A.nodeName&&A.nodeName.toLowerCase();return"select"===M||"input"===M&&"file"===A.type}function g(A){var M=u.getPooled(h.change,z,A,w(A));x.accumulateTwoPhaseDispatches(M),y.batchedUpdates(e,M)}function e(A){s.enqueueEvents(A),s.processEventQueue(!1)}function i(A,M){S=A,z=M,S.attachEvent("onchange",g)}function T(){S&&(S.detachEvent("onchange",g),S=null,z=null)}function E(A,M,t){if(A===d.topChange)return t}function N(A,M,t){A===d.topFocus?(T(),i(M,t)):A===d.topBlur&&T()}function o(A,M){S=A,z=M,p=A.value,U=Object.getOwnPropertyDescriptor(A.constructor.prototype,"value"),Object.defineProperty(S,"value",F),S.attachEvent("onpropertychange",C)}function n(){S&&(delete S.value,S.detachEvent("onpropertychange",C),S=null,z=null,p=null,U=null)}function C(A){if("value"===A.propertyName){var M=A.srcElement.value;M!==p&&(p=M,g(A))}}function c(A,M,t){if(A===d.topInput)return t}function D(A,M,t){A===d.topFocus?(n(),o(M,t)):A===d.topBlur&&n()}function a(A,M,t){if((A===d.topSelectionChange||A===d.topKeyUp||A===d.topKeyDown)&&S&&S.value!==p)return p=S.value,z}function B(A){return A.nodeName&&"input"===A.nodeName.toLowerCase()&&("checkbox"===A.type||"radio"===A.type)}function Q(A,M,t){if(A===d.topClick)return t}var r=t(24),s=t(53),x=t(54),j=t(10),y=t(18),u=t(37),w=t(117),L=t(120),l=t(229),Y=t(27),d=r.topLevelTypes,h={change:{phasedRegistrationNames:{bubbled:Y({onChange:null}),captured:Y({onChangeCapture:null})},dependencies:[d.topBlur,d.topChange,d.topClick,d.topFocus,d.topInput,d.topKeyDown,d.topKeyUp,d.topSelectionChange]}},S=null,z=null,p=null,U=null,O=!1;j.canUseDOM&&(O=L("change")&&(!("documentMode"in document)||document.documentMode>8));var m=!1;j.canUseDOM&&(m=L("input")&&(!("documentMode"in document)||document.documentMode>9));var F={get:function(){return U.get.call(this)},set:function(A){p=""+A,U.set.call(this,A)}},f={eventTypes:h,extractEvents:function(A,M,t,g,e){var i,T;if(I(M)?O?i=E:T=N:l(M)?m?i=c:(i=a,T=D):B(M)&&(i=Q),i){var o=i(A,M,t);if(o){var n=u.getPooled(h.change,o,g,e);return n.type="change",x.accumulateTwoPhaseDispatches(n),n}}T&&T(A,M,t)}};A.exports=f},function(A,M){"use strict";var t=0,I={createReactRootIndex:function(){return t++}};A.exports=I},function(A,M,t){"use strict";function I(A){return A.substring(1,A.indexOf(" "))}var g=t(10),e=t(299),i=t(20),T=t(151),E=t(2),N=/^(<[^ \/>]+)/,o="data-danger-index",n={dangerouslyRenderMarkup:function(A){g.canUseDOM?void 0:E(!1);for(var M,t={},n=0;n1?1-M:void 0;return this._fallbackText=g.slice(A,T),this._fallbackText}}),g.addPoolingTo(I),A.exports=I},function(A,M,t){"use strict";var I,g=t(47),e=t(10),i=g.injection.MUST_USE_ATTRIBUTE,T=g.injection.MUST_USE_PROPERTY,E=g.injection.HAS_BOOLEAN_VALUE,N=g.injection.HAS_SIDE_EFFECTS,o=g.injection.HAS_NUMERIC_VALUE,n=g.injection.HAS_POSITIVE_NUMERIC_VALUE,C=g.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(e.canUseDOM){var c=document.implementation;I=c&&c.hasFeature&&c.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var D={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,acceptCharset:null,accessKey:null,action:null,allowFullScreen:i|E,allowTransparency:i,alt:null,async:E,autoComplete:null,autoPlay:E,capture:i|E,cellPadding:null,cellSpacing:null,charSet:i,challenge:i,checked:T|E,classID:i,className:I?i:T,cols:i|n,colSpan:null,content:null,contentEditable:null,contextMenu:i,controls:T|E,coords:null,crossOrigin:null,data:null,dateTime:i,default:E,defer:E,dir:null,disabled:i|E,download:C,draggable:null,encType:null,form:i,formAction:i,formEncType:i,formMethod:i,formNoValidate:E,formTarget:i,frameBorder:i,headers:null,height:i,hidden:i|E,high:null,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:T,inputMode:i,integrity:null,is:i,keyParams:i,keyType:i,kind:null,label:null,lang:null,list:i,loop:T|E,low:null,manifest:i,marginHeight:null,marginWidth:null,max:null,maxLength:i,media:i,mediaGroup:null,method:null,min:null,minLength:i,multiple:T|E,muted:T|E,name:null,nonce:i,noValidate:E,open:E,optimum:null,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:T|E,rel:null,required:E,reversed:E,role:i,rows:i|n,rowSpan:null,sandbox:null,scope:null,scoped:E,scrolling:null,seamless:i|E,selected:T|E,shape:null,size:i|n,sizes:i,span:n,spellCheck:null,src:null,srcDoc:T,srcLang:null,srcSet:i,start:o,step:null,style:null,summary:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:T|N,width:i,wmode:i,wrap:null,about:i,datatype:i,inlist:i,prefix:i,property:i,resource:i,typeof:i,vocab:i,autoCapitalize:i,autoCorrect:i,autoSave:null,color:null,itemProp:i,itemScope:i|E,itemType:i,itemID:i,itemRef:i,results:null,security:i,unselectable:i},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoComplete:"autocomplete",autoFocus:"autofocus",autoPlay:"autoplay",autoSave:"autosave",encType:"encoding",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};A.exports=D},function(A,M,t){"use strict";var I=t(208),g=t(450),e=t(455),i=t(4),T=t(477),E={};i(E,e),i(E,{findDOMNode:T("findDOMNode","ReactDOM","react-dom",I,I.findDOMNode),render:T("render","ReactDOM","react-dom",I,I.render),unmountComponentAtNode:T("unmountComponentAtNode","ReactDOM","react-dom",I,I.unmountComponentAtNode),renderToString:T("renderToString","ReactDOMServer","react-dom/server",g,g.renderToString),renderToStaticMarkup:T("renderToStaticMarkup","ReactDOMServer","react-dom/server",g,g.renderToStaticMarkup)}),E.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=I,E.__SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=g,A.exports=E},function(A,M,t){"use strict";var I=(t(55),t(114)),g=(t(3),"_getDOMNodeDidWarn"),e={getDOMNode:function(){return this.constructor[g]=!0,I(this)}};A.exports=e},function(A,M,t){"use strict";function I(A,M,t){var I=void 0===A[t];null!=M&&I&&(A[t]=e(M,null))}var g=t(36),e=t(119),i=t(122),T=t(123),E=(t(3),{instantiateChildren:function(A,M,t){if(null==A)return null;var g={};return T(A,I,g),g},updateChildren:function(A,M,t,I){if(!M&&!A)return null;var T;for(T in M)if(M.hasOwnProperty(T)){var E=A&&A[T],N=E&&E._currentElement,o=M[T];if(null!=E&&i(N,o))g.receiveComponent(E,o,t,I),M[T]=E;else{E&&g.unmountComponent(E,T);var n=e(o,null);M[T]=n}}for(T in A)!A.hasOwnProperty(T)||M&&M.hasOwnProperty(T)||g.unmountComponent(A[T]);return M},unmountChildren:function(A){for(var M in A)if(A.hasOwnProperty(M)){var t=A[M];g.unmountComponent(t)}}});A.exports=E},function(A,M,t){"use strict";function I(A){var M=A._currentElement._owner||null;if(M){var t=M.getName();if(t)return" Check the render method of ` + "`" + `"+t+"` + "`" + `."}return""}function g(A){}var e=t(110),i=t(25),T=t(13),E=t(55),N=t(17),o=t(71),n=(t(70),t(36)),C=t(112),c=t(4),D=t(50),a=t(2),B=t(122);t(3);g.prototype.render=function(){var A=E.get(this)._currentElement.type;return A(this.props,this.context,this.updater)};var Q=1,r={construct:function(A){this._currentElement=A,this._rootNodeID=null,this._instance=null,this._pendingElement=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._renderedComponent=null,this._context=null,this._mountOrder=0,this._topLevelWrapper=null,this._pendingCallbacks=null},mountComponent:function(A,M,t){this._context=t,this._mountOrder=Q++,this._rootNodeID=A;var I,e,i=this._processProps(this._currentElement.props),N=this._processContext(t),o=this._currentElement.type,c="prototype"in o;c&&(I=new o(i,N,C)),c&&null!==I&&I!==!1&&!T.isValidElement(I)||(e=I,I=new g(o)),I.props=i,I.context=N,I.refs=D,I.updater=C,this._instance=I,E.set(I,this);var B=I.state;void 0===B&&(I.state=B=null),"object"!=typeof B||Array.isArray(B)?a(!1):void 0,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,I.componentWillMount&&(I.componentWillMount(),this._pendingStateQueue&&(I.state=this._processPendingState(I.props,I.context))),void 0===e&&(e=this._renderValidatedComponent()),this._renderedComponent=this._instantiateReactComponent(e);var r=n.mountComponent(this._renderedComponent,A,M,this._processChildContext(t));return I.componentDidMount&&M.getReactMountReady().enqueue(I.componentDidMount,I),r},unmountComponent:function(){var A=this._instance;A.componentWillUnmount&&A.componentWillUnmount(),n.unmountComponent(this._renderedComponent),this._renderedComponent=null,this._instance=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._pendingCallbacks=null,this._pendingElement=null,this._context=null,this._rootNodeID=null,this._topLevelWrapper=null,E.remove(A)},_maskContext:function(A){var M=null,t=this._currentElement.type,I=t.contextTypes;if(!I)return D;M={};for(var g in I)M[g]=A[g];return M},_processContext:function(A){var M=this._maskContext(A);return M},_processChildContext:function(A){var M=this._currentElement.type,t=this._instance,I=t.getChildContext&&t.getChildContext();if(I){"object"!=typeof M.childContextTypes?a(!1):void 0;for(var g in I)g in M.childContextTypes?void 0:a(!1);return c({},A,I)}return A},_processProps:function(A){return A},_checkPropTypes:function(A,M,t){var g=this.getName();for(var e in A)if(A.hasOwnProperty(e)){var i;try{"function"!=typeof A[e]?a(!1):void 0,i=A[e](M,e,g,t)}catch(A){i=A}if(i instanceof Error){I(this);t===o.prop}}},receiveComponent:function(A,M,t){var I=this._currentElement,g=this._context;this._pendingElement=null,this.updateComponent(M,I,A,g,t)},performUpdateIfNecessary:function(A){null!=this._pendingElement&&n.receiveComponent(this,this._pendingElement||this._currentElement,A,this._context),(null!==this._pendingStateQueue||this._pendingForceUpdate)&&this.updateComponent(A,this._currentElement,this._currentElement,this._context,this._context)},updateComponent:function(A,M,t,I,g){var e,i=this._instance,T=this._context===g?i.context:this._processContext(g);M===t?e=t.props:(e=this._processProps(t.props),i.componentWillReceiveProps&&i.componentWillReceiveProps(e,T));var E=this._processPendingState(e,T),N=this._pendingForceUpdate||!i.shouldComponentUpdate||i.shouldComponentUpdate(e,E,T);N?(this._pendingForceUpdate=!1,this._performComponentUpdate(t,e,E,T,A,g)):(this._currentElement=t,this._context=g,i.props=e,i.state=E,i.context=T)},_processPendingState:function(A,M){var t=this._instance,I=this._pendingStateQueue,g=this._pendingReplaceState;if(this._pendingReplaceState=!1,this._pendingStateQueue=null,!I)return t.state;if(g&&1===I.length)return I[0];for(var e=c({},g?I[0]:t.state),i=g?1:0;i=0||null!=M.is}function B(A){D(A),this._tag=A.toLowerCase(),this._renderedChildren=null,this._previousStyle=null,this._previousStyleCopy=null,this._rootNodeID=null,this._wrapperState=null,this._topLevelWrapper=null,this._nodeWithLegacyProperties=null}var Q=t(429),r=t(431),s=t(47),x=t(107),j=t(24),y=t(69),u=t(109),w=t(444),L=t(447),l=t(448),Y=t(210),d=t(451),h=t(12),S=t(456),z=t(17),p=t(112),U=t(4),O=t(74),m=t(75),F=t(2),f=(t(120),t(27)),k=t(76),R=t(121),J=(t(152),t(124),t(3),y.deleteListener),G=y.listenTo,H=y.registrationNameModules,b={string:!0,number:!0},X=f({children:null}),v=f({style:null}),W=f({__html:null}),V=1,P={topAbort:"abort",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topSeeked:"seeked",topSeeking:"seeking",topStalled:"stalled",topSuspend:"suspend",topTimeUpdate:"timeupdate",topVolumeChange:"volumechange",topWaiting:"waiting"},Z={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},K={listing:!0,pre:!0,textarea:!0},q=(U({menuitem:!0},Z),/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/),_={},$={}.hasOwnProperty;B.displayName="ReactDOMComponent",B.Mixin={construct:function(A){this._currentElement=A},mountComponent:function(A,M,t){this._rootNodeID=A;var I=this._currentElement.props;switch(this._tag){case"iframe":case"img":case"form":case"video":case"audio":this._wrapperState={listeners:null},M.getReactMountReady().enqueue(n,this);break;case"button":I=w.getNativeProps(this,I,t);break;case"input":L.mountWrapper(this,I,t),I=L.getNativeProps(this,I,t);break;case"option":l.mountWrapper(this,I,t),I=l.getNativeProps(this,I,t);break;case"select":Y.mountWrapper(this,I,t),I=Y.getNativeProps(this,I,t),t=Y.processChildContext(this,I,t);break;case"textarea":d.mountWrapper(this,I,t),I=d.getNativeProps(this,I,t)}E(this,I);var g;if(M.useCreateElement){var e=t[h.ownerDocumentContextKey],i=e.createElement(this._currentElement.type);x.setAttributeForID(i,this._rootNodeID),h.getID(i),this._updateDOMProperties({},I,M,i),this._createInitialChildren(M,I,t,i),g=i}else{var T=this._createOpenTagMarkupAndPutListeners(M,I),N=this._createContentMarkup(M,I,t);g=!N&&Z[this._tag]?T+"/>":T+">"+N+""}switch(this._tag){case"input":M.getReactMountReady().enqueue(C,this);case"button":case"select":case"textarea":I.autoFocus&&M.getReactMountReady().enqueue(Q.focusDOMComponent,this)}return g},_createOpenTagMarkupAndPutListeners:function(A,M){var t="<"+this._currentElement.type;for(var I in M)if(M.hasOwnProperty(I)){var g=M[I];if(null!=g)if(H.hasOwnProperty(I))g&&N(this._rootNodeID,I,g,A);else{I===v&&(g&&(g=this._previousStyleCopy=U({},M.style)),g=r.createMarkupForStyles(g));var e=null;null!=this._tag&&a(this._tag,M)?I!==X&&(e=x.createMarkupForCustomAttribute(I,g)):e=x.createMarkupForProperty(I,g),e&&(t+=" "+e)}}if(A.renderToStaticMarkup)return t;var i=x.createMarkupForID(this._rootNodeID);return t+" "+i},_createContentMarkup:function(A,M,t){var I="",g=M.dangerouslySetInnerHTML;if(null!=g)null!=g.__html&&(I=g.__html);else{var e=b[typeof M.children]?M.children:null,i=null!=e?null:M.children;if(null!=e)I=m(e);else if(null!=i){var T=this.mountChildren(i,A,t);I=T.join("")}}return K[this._tag]&&"\n"===I.charAt(0)?"\n"+I:I},_createInitialChildren:function(A,M,t,I){var g=M.dangerouslySetInnerHTML;if(null!=g)null!=g.__html&&k(I,g.__html);else{var e=b[typeof M.children]?M.children:null,i=null!=e?null:M.children;if(null!=e)R(I,e);else if(null!=i)for(var T=this.mountChildren(i,A,t),E=0;EM.end?(t=M.end,I=M.start):(t=M.start,I=M.end),g.moveToElementText(A),g.moveStart("character",t),g.setEndPoint("EndToStart",g),g.moveEnd("character",I-t),g.select()}function T(A,M){if(window.getSelection){var t=window.getSelection(),I=A[o()].length,g=Math.min(M.start,I),e="undefined"==typeof M.end?g:Math.min(M.end,I);if(!t.extend&&g>e){var i=e;e=g,g=i}var T=N(A,g),E=N(A,e);if(T&&E){var n=document.createRange();n.setStart(T.node,T.offset),t.removeAllRanges(),g>e?(t.addRange(n),t.extend(E.node,E.offset)):(n.setEnd(E.node,E.offset),t.addRange(n))}}}var E=t(10),N=t(480),o=t(228),n=E.canUseDOM&&"selection"in document&&!("getSelection"in window),C={getOffsets:n?g:e,setOffsets:n?i:T};A.exports=C},function(A,M,t){"use strict";var I=t(213),g=t(461),e=t(113);I.inject();var i={renderToString:g.renderToString,renderToStaticMarkup:g.renderToStaticMarkup,version:e};A.exports=i},function(A,M,t){"use strict";function I(){this._rootNodeID&&o.updateWrapper(this)}function g(A){var M=this._currentElement.props,t=e.executeOnChange(M,A);return T.asap(I,this),t}var e=t(108),i=t(111),T=t(18),E=t(4),N=t(2),o=(t(3),{getNativeProps:function(A,M,t){null!=M.dangerouslySetInnerHTML?N(!1):void 0;var I=E({},M,{defaultValue:void 0,value:void 0,children:A._wrapperState.initialValue,onChange:A._wrapperState.onChange});return I},mountWrapper:function(A,M){var t=M.defaultValue,I=M.children;null!=I&&(null!=t?N(!1):void 0,Array.isArray(I)&&(I.length<=1?void 0:N(!1),I=I[0]),t=""+I),null==t&&(t="");var i=e.getValue(M);A._wrapperState={initialValue:""+(null!=i?i:t),onChange:g.bind(A)}},updateWrapper:function(A){var M=A._currentElement.props,t=e.getValue(M);null!=t&&i.updatePropertyByID(A._rootNodeID,"value",""+t)}});A.exports=o},function(A,M,t){"use strict";function I(A){g.enqueueEvents(A),g.processEventQueue(!1)}var g=t(53),e={handleTopLevel:function(A,M,t,e,i){var T=g.extractEvents(A,M,t,e,i);I(T)}};A.exports=e},function(A,M,t){"use strict";function I(A){var M=C.getID(A),t=n.getReactRootIDFromNodeID(M),I=C.findReactContainerForID(t),g=C.getFirstReactDOM(I);return g}function g(A,M){this.topLevelType=A,this.nativeEvent=M,this.ancestors=[]}function e(A){i(A)}function i(A){for(var M=C.getFirstReactDOM(a(A.nativeEvent))||window,t=M;t;)A.ancestors.push(t),t=I(t);for(var g=0;g=M)return{node:g,offset:M-e};e=i}g=t(I(g))}}A.exports=g},function(A,M,t){"use strict";function I(A){return g.isValidElement(A)?void 0:e(!1),A}var g=t(13),e=t(2);A.exports=I},function(A,M,t){"use strict";function I(A){return'"'+g(A)+'"'}var g=t(75);A.exports=I},function(A,M,t){"use strict";var I=t(12);A.exports=I.renderSubtreeIntoContainer},function(A,M){A.exports=function(A,M,t){for(var I=0,g=A.length,e=3==arguments.length?t:A[I++];I=400){ +var T="cannot "+M.method+" "+M.url+" ("+i.status+")";A=new e(T),A.status=i.status,A.body=i.body,A.res=i,I(A)}else g?I(new e(g)):t(i)})})},g.prototype.then=function(){var A=this.promise();return A.then.apply(A,arguments)}},function(A,M,t){function I(){}function g(A){var M={}.toString.call(A);switch(M){case"[object File]":case"[object Blob]":case"[object FormData]":return!0;default:return!1}}function e(A){if(!s(A))return A;var M=[];for(var t in A)null!=A[t]&&i(M,t,A[t]);return M.join("&")}function i(A,M,t){return Array.isArray(t)?t.forEach(function(t){i(A,M,t)}):void A.push(encodeURIComponent(M)+"="+encodeURIComponent(t))}function T(A){for(var M,t,I={},g=A.split("&"),e=0,i=g.length;e=200&&M.status<300)return t.callback(A,M);var I=new Error(M.statusText||"Unsuccessful HTTP response");I.original=A,I.response=M,I.status=M.status,t.callback(I,M)})}function D(A,M){var t=x("DELETE",A);return M&&t.end(M),t}var a,B=t(273),Q=t(484),r=t(502),s=t(236);a="undefined"!=typeof window?window:"undefined"!=typeof self?self:this;var x=A.exports=t(503).bind(null,c);x.getXHR=function(){if(!(!a.XMLHttpRequest||a.location&&"file:"==a.location.protocol&&a.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(A){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(A){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(A){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(A){}return!1};var j="".trim?function(A){return A.trim()}:function(A){return A.replace(/(^\s*|\s*$)/g,"")};x.serializeObject=e,x.parseString=T,x.types={html:"text/html",json:"application/json",xml:"application/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},x.serialize={"application/x-www-form-urlencoded":e,"application/json":JSON.stringify},x.parse={"application/x-www-form-urlencoded":T,"application/json":JSON.parse},C.prototype.get=function(A){return this.header[A.toLowerCase()]},C.prototype.setHeaderProperties=function(A){var M=this.header["content-type"]||"";this.type=o(M);var t=n(M);for(var I in t)this[I]=t[I]},C.prototype.parseBody=function(A){var M=x.parse[this.type];return!M&&N(this.type)&&(M=x.parse["application/json"]),M&&A&&(A.length||A instanceof Object)?M(A):null},C.prototype.setStatusProperties=function(A){1223===A&&(A=204);var M=A/100|0;this.status=this.statusCode=A,this.statusType=M,this.info=1==M,this.ok=2==M,this.clientError=4==M,this.serverError=5==M,this.error=(4==M||5==M)&&this.toError(),this.accepted=202==A,this.noContent=204==A,this.badRequest=400==A,this.unauthorized=401==A,this.notAcceptable=406==A,this.notFound=404==A,this.forbidden=403==A},C.prototype.toError=function(){var A=this.req,M=A.method,t=A.url,I="cannot "+M+" "+t+" ("+this.status+")",g=new Error(I);return g.status=this.status,g.method=M,g.url=t,g},x.Response=C,B(c.prototype);for(var y in r)c.prototype[y]=r[y];c.prototype.abort=function(){if(!this.aborted)return this.aborted=!0,this.xhr&&this.xhr.abort(),this.clearTimeout(),this.emit("abort"),this},c.prototype.type=function(A){return this.set("Content-Type",x.types[A]||A),this},c.prototype.responseType=function(A){return this._responseType=A,this},c.prototype.accept=function(A){return this.set("Accept",x.types[A]||A),this},c.prototype.auth=function(A,M,t){switch(t||(t={type:"basic"}),t.type){case"basic":var I=btoa(A+":"+M);this.set("Authorization","Basic "+I);break;case"auto":this.username=A,this.password=M}return this},c.prototype.query=function(A){return"string"!=typeof A&&(A=e(A)),A&&this._query.push(A),this},c.prototype.attach=function(A,M,t){return this._getFormData().append(A,M,t||M.name),this},c.prototype._getFormData=function(){return this._formData||(this._formData=new a.FormData),this._formData},c.prototype.send=function(A){var M=s(A),t=this._header["content-type"];if(M&&s(this._data))for(var I in A)this._data[I]=A[I];else"string"==typeof A?(t||this.type("form"),t=this._header["content-type"],"application/x-www-form-urlencoded"==t?this._data=this._data?this._data+"&"+A:A:this._data=(this._data||"")+A):this._data=A;return!M||g(A)?this:(t||this.type("json"),this)},C.prototype.parse=function(A){return a.console&&console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0"),this.serialize(A),this},C.prototype.serialize=function(A){return this._parser=A,this},c.prototype.callback=function(A,M){var t=this._callback;this.clearTimeout(),t(A,M)},c.prototype.crossDomainError=function(){var A=new Error("Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.");A.crossDomain=!0,A.status=this.status,A.method=this.method,A.url=this.url,this.callback(A)},c.prototype.timeoutError=function(){var A=this._timeout,M=new Error("timeout of "+A+"ms exceeded");M.timeout=A,this.callback(M)},c.prototype.withCredentials=function(){return this._withCredentials=!0,this},c.prototype.end=function(A){var M=this,t=this.xhr=x.getXHR(),e=this._query.join("&"),i=this._timeout,T=this._formData||this._data;this._callback=A||I,t.onreadystatechange=function(){if(4==t.readyState){var A;try{A=t.status}catch(M){A=0}if(0==A){if(M.timedout)return M.timeoutError();if(M.aborted)return;return M.crossDomainError()}M.emit("end")}};var E=function(A){A.total>0&&(A.percent=A.loaded/A.total*100),A.direction="download",M.emit("progress",A)};this.hasListeners("progress")&&(t.onprogress=E);try{t.upload&&this.hasListeners("progress")&&(t.upload.onprogress=E)}catch(A){}if(i&&!this._timer&&(this._timer=setTimeout(function(){M.timedout=!0,M.abort()},i)),e&&(e=x.serializeObject(e),this.url+=~this.url.indexOf("?")?"&"+e:"?"+e),this.username&&this.password?t.open(this.method,this.url,!0,this.username,this.password):t.open(this.method,this.url,!0),this._withCredentials&&(t.withCredentials=!0),"GET"!=this.method&&"HEAD"!=this.method&&"string"!=typeof T&&!g(T)){var o=this._header["content-type"],n=this._parser||x.serialize[o?o.split(";")[0]:""];!n&&N(o)&&(n=x.serialize["application/json"]),n&&(T=n(T))}for(var C in this.header)null!=this.header[C]&&t.setRequestHeader(C,this.header[C]);return this._responseType&&(t.responseType=this._responseType),this.emit("request",this),t.send("undefined"!=typeof T?T:null),this},x.Request=c,x.get=function(A,M,t){var I=x("GET",A);return"function"==typeof M&&(t=M,M=null),M&&I.query(M),t&&I.end(t),I},x.head=function(A,M,t){var I=x("HEAD",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I},x.del=D,x.delete=D,x.patch=function(A,M,t){var I=x("PATCH",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I},x.post=function(A,M,t){var I=x("POST",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I},x.put=function(A,M,t){var I=x("PUT",A);return"function"==typeof M&&(t=M,M=null),M&&I.send(M),t&&I.end(t),I}},function(A,M,t){var I=t(236);M.clearTimeout=function(){return this._timeout=0,clearTimeout(this._timer),this},M.parse=function(A){return this._parser=A,this},M.timeout=function(A){return this._timeout=A,this},M.then=function(A,M){return this.end(function(t,I){t?M(t):A(I)})},M.use=function(A){return A(this),this},M.get=function(A){return this._header[A.toLowerCase()]},M.getHeader=M.get,M.set=function(A,M){if(I(A)){for(var t in A)this.set(t,A[t]);return this}return this._header[A.toLowerCase()]=M,this.header[A]=M,this},M.unset=function(A){return delete this._header[A.toLowerCase()],delete this.header[A],this},M.field=function(A,M){return this._getFormData().append(A,M),this}},function(A,M){function t(A,M,t){return"function"==typeof t?new A("GET",M).end(t):2==arguments.length?new A("GET",M):new A(M,t)}A.exports=t},function(A,M,t){A.exports=t(505)},function(A,M,t){(function(A,I){"use strict";function g(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var e,i=t(506),T=g(i);e="undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof A?A:I;var E=(0,T.default)(e);M.default=E}).call(M,function(){return this}(),t(128)(A))},function(A,M){"use strict";function t(A){var M,t=A.Symbol;return"function"==typeof t?t.observable?M=t.observable:(M=t("observable"),t.observable=M):M="@@observable",M}Object.defineProperty(M,"__esModule",{value:!0}),M.default=t},function(A,M,t){function I(A){return g(A).replace(/\s(\w)/g,function(A,M){return M.toUpperCase()})}var g=t(509);A.exports=I},function(A,M){function t(A){return e.test(A)?A.toLowerCase():i.test(A)?(I(A)||A).toLowerCase():T.test(A)?g(A).toLowerCase():A.toLowerCase()}function I(A){return A.replace(E,function(A,M){return M?" "+M:""})}function g(A){return A.replace(N,function(A,M,t){return M+" "+t.toLowerCase().split("").join(" ")})}A.exports=t;var e=/\s/,i=/(_|-|\.|:)/,T=/([a-z][A-Z]|[A-Z][a-z])/,E=/[\W_]+(.|$)/g,N=/(.)([A-Z]+)/g},function(A,M,t){function I(A){return g(A).replace(/[\W_]+(.|$)/g,function(A,M){return M?" "+M:""}).trim()}var g=t(508);A.exports=I},function(A,M){A.exports=function(){var A=document.getSelection();if(!A.rangeCount)return function(){};for(var M=document.activeElement,t=[],I=0;I=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function i(A,M){function t(I,g){function i(A,t){var I=c.getLinkName(A),e=this.props[g[A]];I&&E(this.props,I)&&!e&&(e=this.props[I].requestChange);for(var i=arguments.length,T=Array(i>2?i-2:0),N=2;N=15||0===s[0]&&s[1]>=13?A:A.type}function T(A,M){var t=N(M);return t&&!E(A,M)&&E(A,t)?A[t].value:A[M]}function E(A,M){return void 0!==A[M]}function N(A){return"value"===A?"valueLink":"checked"===A?"checkedLink":null}function o(A){return"default"+A.charAt(0).toUpperCase()+A.substr(1)}function n(A,M,t){return function(){for(var I=arguments.length,g=Array(I),e=0;e1&&(I=t[0]+"@",A=t[1]),A=A.replace(z,".");var g=A.split("."),e=T(g,M).join(".");return I+e}function N(A){for(var M,t,I=[],g=0,e=A.length;g=55296&&M<=56319&&g65535&&(A-=65536,M+=m(A>>>10&1023|55296),A=56320|1023&A),M+=m(A)}).join("")}function n(A){return A-48<10?A-22:A-65<26?A-65:A-97<26?A-97:j}function C(A,M){return A+22+75*(A<26)-((0!=M)<<5)}function c(A,M,t){var I=0;for(A=t?O(A/L):A>>1,A+=O(A/M);A>p*u>>1;I+=j)A=O(A/p);return O(I+(p+1)*A/(A+w))}function D(A){var M,t,I,g,e,T,E,N,C,D,a=[],B=A.length,Q=0,r=Y,s=l;for(t=A.lastIndexOf(d),t<0&&(t=0),I=0;I=128&&i("not-basic"),a.push(A.charCodeAt(I));for(g=t>0?t+1:0;g=B&&i("invalid-input"),N=n(A.charCodeAt(g++)),(N>=j||N>O((x-Q)/T))&&i("overflow"),Q+=N*T,C=E<=s?y:E>=s+u?u:E-s,!(NO(x/D)&&i("overflow"),T*=D;M=a.length+1,s=c(Q-e,M,0==e),O(Q/M)>x-r&&i("overflow"),r+=O(Q/M),Q%=M,a.splice(Q++,0,r)}return o(a)}function a(A){var M,t,I,g,e,T,E,o,n,D,a,B,Q,r,s,w=[];for(A=N(A),B=A.length,M=Y,t=0,e=l,T=0;T=M&&aO((x-t)/Q)&&i("overflow"),t+=(E-M)*Q,M=E,T=0;Tx&&i("overflow"),a==M){for(o=t,n=j;D=n<=e?y:n>=e+u?u:n-e,!(o= 0x80 (not a basic code point)","invalid-input":"Invalid input"},p=j-y,O=Math.floor,m=String.fromCharCode;s={version:"1.3.2",ucs2:{decode:N,encode:o},decode:D,encode:a,toASCII:Q,toUnicode:B},I=function(){return s}.call(M,t,M,A),!(void 0!==I&&(A.exports=I))}(this)}).call(M,t(128)(A),function(){return this}())},function(A,M){"use strict";A.exports={isString:function(A){return"string"==typeof A},isObject:function(A){return"object"==typeof A&&null!==A},isNull:function(A){return null===A},isNullOrUndefined:function(A){return null==A}}}]);`) +},function(A,M,t){var I;(function(A,g){!function(e){function i(A){throw RangeError(p[A])}function T(A,M){for(var t=A.length,I=[];t--;)I[t]=M(A[t]);return I}function E(A,M){var t=A.split("@"),I="";t.length>1&&(I=t[0]+"@",A=t[1]),A=A.replace(z,".");var g=A.split("."),e=T(g,M).join(".");return I+e}function N(A){for(var M,t,I=[],g=0,e=A.length;g=55296&&M<=56319&&g65535&&(A-=65536,M+=m(A>>>10&1023|55296),A=56320|1023&A),M+=m(A)}).join("")}function n(A){return A-48<10?A-22:A-65<26?A-65:A-97<26?A-97:j}function C(A,M){return A+22+75*(A<26)-((0!=M)<<5)}function c(A,M,t){var I=0;for(A=t?O(A/L):A>>1,A+=O(A/M);A>U*u>>1;I+=j)A=O(A/U);return O(I+(U+1)*A/(A+w))}function D(A){var M,t,I,g,e,T,E,N,C,D,a=[],B=A.length,Q=0,r=Y,s=l;for(t=A.lastIndexOf(d),t<0&&(t=0),I=0;I=128&&i("not-basic"),a.push(A.charCodeAt(I));for(g=t>0?t+1:0;g=B&&i("invalid-input"),N=n(A.charCodeAt(g++)),(N>=j||N>O((x-Q)/T))&&i("overflow"),Q+=N*T,C=E<=s?y:E>=s+u?u:E-s,!(NO(x/D)&&i("overflow"),T*=D;M=a.length+1,s=c(Q-e,M,0==e),O(Q/M)>x-r&&i("overflow"),r+=O(Q/M),Q%=M,a.splice(Q++,0,r)}return o(a)}function a(A){var M,t,I,g,e,T,E,o,n,D,a,B,Q,r,s,w=[];for(A=N(A),B=A.length,M=Y,t=0,e=l,T=0;T=M&&aO((x-t)/Q)&&i("overflow"),t+=(E-M)*Q,M=E,T=0;Tx&&i("overflow"),a==M){for(o=t,n=j;D=n<=e?y:n>=e+u?u:n-e,!(o= 0x80 (not a basic code point)","invalid-input":"Invalid input"},U=j-y,O=Math.floor,m=String.fromCharCode;s={version:"1.3.2",ucs2:{decode:N,encode:o},decode:D,encode:a,toASCII:Q,toUnicode:B},I=function(){return s}.call(M,t,M,A),!(void 0!==I&&(A.exports=I))}(this)}).call(M,t(128)(A),function(){return this}())},function(A,M){"use strict";A.exports={isString:function(A){return"string"==typeof A},isObject:function(A){return"object"==typeof A&&null!==A},isNull:function(A){return null===A},isNullOrUndefined:function(A){return null==A}}}]);`) -func productionIndex_bundle20170202t110000zJsBytes() ([]byte, error) { - return _productionIndex_bundle20170202t110000zJs, nil +func productionIndex_bundle20170215t192644zJsBytes() ([]byte, error) { + return _productionIndex_bundle20170215t192644zJs, nil } -func productionIndex_bundle20170202t110000zJs() (*asset, error) { - bytes, err := productionIndex_bundle20170202t110000zJsBytes() +func productionIndex_bundle20170215t192644zJs() (*asset, error) { + bytes, err := productionIndex_bundle20170215t192644zJsBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "production/index_bundle-2017-02-02T11-00-00Z.js", size: 2271935, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/index_bundle-2017-02-15T19-26-44Z.js", size: 2276742, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -370,7 +370,7 @@ func productionLoaderCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -444,7 +444,7 @@ func productionLogoSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -461,7 +461,7 @@ func productionSafariPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1486033217, 0)} + info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -522,7 +522,7 @@ var _bindata = map[string]func() (*asset, error){ "production/favicon.ico": productionFaviconIco, "production/firefox.png": productionFirefoxPng, "production/index.html": productionIndexHTML, - "production/index_bundle-2017-02-02T11-00-00Z.js": productionIndex_bundle20170202t110000zJs, + "production/index_bundle-2017-02-15T19-26-44Z.js": productionIndex_bundle20170215t192644zJs, "production/loader.css": productionLoaderCss, "production/logo.svg": productionLogoSvg, "production/safari.png": productionSafariPng, @@ -574,7 +574,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "favicon.ico": {productionFaviconIco, map[string]*bintree{}}, "firefox.png": {productionFirefoxPng, map[string]*bintree{}}, "index.html": {productionIndexHTML, map[string]*bintree{}}, - "index_bundle-2017-02-02T11-00-00Z.js": {productionIndex_bundle20170202t110000zJs, map[string]*bintree{}}, + "index_bundle-2017-02-15T19-26-44Z.js": {productionIndex_bundle20170215t192644zJs, map[string]*bintree{}}, "loader.css": {productionLoaderCss, map[string]*bintree{}}, "logo.svg": {productionLogoSvg, map[string]*bintree{}}, "safari.png": {productionSafariPng, map[string]*bintree{}}, @@ -635,6 +635,6 @@ func assetFS() *assetfs.AssetFS { panic("unreachable") } -var UIReleaseTag = "RELEASE.2017-02-02T11-00-00Z" -var UICommitID = "fc446e0b812eb1c6c56a413a3c77e818227394bd" -var UIVersion = "2017-02-02T11:00:00Z" +var UIReleaseTag = "RELEASE.2017-02-15T19-26-44Z" +var UICommitID = "7f86a21317f8369324ecc447a0a0bf01b60fac3e" +var UIVersion = "2017-02-15T19:26:44Z" diff --git a/browser/yarn.lock b/browser/yarn.lock index 003765826..f6f193a78 100644 --- a/browser/yarn.lock +++ b/browser/yarn.lock @@ -694,6 +694,10 @@ babylon@^6.11.0, babylon@^6.15.0, babylon@^6.8.0: version "6.15.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e" +babylon@6.14.1: + version "6.14.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" + backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -756,7 +760,7 @@ bluebird@^2.10.2, bluebird@^2.9.27: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" -bluebird@^3.4.7: +bluebird@^3.0.5, bluebird@^3.4.7: version "3.4.7" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" @@ -1086,6 +1090,13 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +config-chain@~1.1.5: + version "1.1.11" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + connect-history-api-fallback@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169" @@ -1462,6 +1473,15 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +editorconfig@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.2.tgz#8e57926d9ee69ab6cb999f027c2171467acceb35" + dependencies: + bluebird "^3.0.5" + commander "^2.9.0" + lru-cache "^3.2.0" + sigmund "^1.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1571,6 +1591,10 @@ escape-string-regexp@^1.0.2, escape-string-regexp@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" +esformatter-ignore@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/esformatter-ignore/-/esformatter-ignore-0.1.3.tgz#04d3b875bfa49dde004cc58df6f6bbc3c0567f1e" + esformatter-jsx-ignore@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/esformatter-jsx-ignore/-/esformatter-jsx-ignore-1.0.6.tgz#e594f6b77db6f85d8c1179ae6dc465756d422489" @@ -1578,6 +1602,15 @@ esformatter-jsx-ignore@^1.0.6: esprima-fb "^12001.1.0-dev-harmony-fb" fresh-falafel "^0.2.6" +esformatter-jsx@^7.4.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/esformatter-jsx/-/esformatter-jsx-7.4.1.tgz#b2209ae0908f413a747b1205727cbf4ba4249602" + dependencies: + babylon "6.14.1" + esformatter-ignore "^0.1.3" + extend "3.0.0" + js-beautify "1.6.4" + esformatter-parser@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esformatter-parser/-/esformatter-parser-1.0.0.tgz#0854072d0487539ed39cae38d8a5432c17ec11d3" @@ -2200,7 +2233,7 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -ini@~1.3.0: +ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" @@ -2428,6 +2461,15 @@ js-base64@^2.1.9: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" +js-beautify@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.6.4.tgz#a9af79699742ac9a1b6fddc1fdbc78bc4d515fc3" + dependencies: + config-chain "~1.1.5" + editorconfig "^0.13.2" + mkdirp "~0.5.0" + nopt "~3.0.1" + js-tokens@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.0.tgz#a2f2a969caae142fb3cd56228358c89366957bd1" @@ -2684,6 +2726,12 @@ lower-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.3.tgz#c92393d976793eee5ba4edb583cf8eae35bd9bfb" +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + dependencies: + pseudomap "^1.0.1" + lru-cache@2: version "2.7.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" @@ -2902,7 +2950,7 @@ node-pre-gyp@^0.6.29: tar "~2.2.1" tar-pack "~3.3.0" -nopt@~3.0.6: +nopt@~3.0.1, nopt@~3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: @@ -3447,6 +3495,10 @@ promise@^7.0.3, promise@^7.1.1: dependencies: asap "~2.0.3" +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + protochain@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260" @@ -3462,6 +3514,10 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -3609,6 +3665,10 @@ react-dropzone@^3.5.3: dependencies: attr-accept "^1.0.3" +react-infinite-scroller@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.0.6.tgz#bb406d70032d09fa9e4a3e2175d3adbf4a3f559d" + react-onclickout@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/react-onclickout/-/react-onclickout-2.0.4.tgz#2c7539a647e1dcdcab0b28e2f4eae3c3e00f0c64" @@ -4039,7 +4099,7 @@ shelljs@^0.7.0: interpret "^1.0.0" rechoir "^0.6.2" -sigmund@~1.0.0: +sigmund@^1.0.1, sigmund@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" From ae4656e69955cd569dd70d0f417a973816b13d8d Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Wed, 15 Feb 2017 13:07:47 -0800 Subject: [PATCH 74/75] browser: Remove currentPath prefix in object names from list result. (#3750) --- browser/app/js/actions.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/browser/app/js/actions.js b/browser/app/js/actions.js index 2acf688e1..c9b2f72bf 100644 --- a/browser/app/js/actions.js +++ b/browser/app/js/actions.js @@ -304,9 +304,13 @@ export const listObjects = () => { marker: marker }) .then(res => { - let objects = res.objects - if (!objects.length) + let objects = res.objects + if (!objects) objects = [] + objects = objects.map(object => { + object.name = object.name.replace(`${currentPath}`, ''); + return object + }) dispatch(setObjects(objects, res.nextmarker, res.istruncated)) dispatch(setPrefixWritable(res.writable)) dispatch(setLoadBucket('')) @@ -328,7 +332,7 @@ export const listObjects = () => { export const selectPrefix = prefix => { return (dispatch, getState) => { const {currentBucket, web} = getState() - dispatch(setObjects([], "", true)) + dispatch(setObjects([], "", false)) dispatch(setLoadPath(prefix)) web.ListObjects({ bucketName: currentBucket, @@ -339,6 +343,10 @@ export const selectPrefix = prefix => { let objects = res.objects if (!objects) objects = [] + objects = objects.map(object => { + object.name = object.name.replace(`${prefix}`, ''); + return object + }) dispatch(setObjects( objects, res.nextmarker, From 3e770defae48e86f4406209d3942dcac85cba73a Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Wed, 15 Feb 2017 14:28:09 -0800 Subject: [PATCH 75/75] browser: Update ui assets with new changes (#3751) --- browser/ui-assets.go | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/browser/ui-assets.go b/browser/ui-assets.go index a8c48406d..773e9288b 100644 --- a/browser/ui-assets.go +++ b/browser/ui-assets.go @@ -4,7 +4,7 @@ // production/favicon.ico // production/firefox.png // production/index.html -// production/index_bundle-2017-02-15T19-26-44Z.js +// production/index_bundle-2017-02-15T22-41-23Z.js // production/loader.css // production/logo.svg // production/safari.png @@ -65,7 +65,7 @@ func productionChromePng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/chrome.png", size: 3726, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -82,7 +82,7 @@ func productionFaviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/favicon.ico", size: 1340, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -99,7 +99,7 @@ func productionFirefoxPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/firefox.png", size: 4795, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -156,8 +156,8 @@ var _productionIndexHTML = []byte(` - - + + `) @@ -172,21 +172,21 @@ func productionIndexHTML() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/index.html", size: 1996, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _productionIndex_bundle20170215t192644zJs = []byte(`!function(A){function M(I){if(t[I])return t[I].exports;var g=t[I]={exports:{},id:I,loaded:!1};return A[I].call(g.exports,g,g.exports,M),g.loaded=!0,g.exports}var t={};return M.m=A,M.c=t,M.p="",M(0)}([function(A,M,t){A.exports=t(240)},function(A,M,t){"use strict";A.exports=t(440)},function(A,M,t){"use strict";function I(A,M,t,I,g,e,i,T){if(!A){var E;if(void 0===M)E=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var N=[t,I,g,e,i,T],o=0;E=new Error(M.replace(/%s/g,function(){return N[o++]})),E.name="Invariant Violation"}throw E.framesToPop=1,E}}A.exports=I},function(A,M,t){"use strict";var I=t(20),g=I;A.exports=g},function(A,M){"use strict";function t(A,M){if(null==A)throw new TypeError("Object.assign target cannot be null or undefined");for(var t=Object(A),I=Object.prototype.hasOwnProperty,g=1;g2?t-2:0),g=2;g1){for(var c=Array(C),D=0;D1){for(var a=Array(D),B=0;B3&&void 0!==arguments[3]?arguments[3]:{},N=Boolean(A),C=A||w,D=void 0;D="function"==typeof M?M:M?(0,Q.default)(M):L;var B=t||l,r=I.pure,s=void 0===r||r,x=I.withRef,y=void 0!==x&&x,h=s&&B!==l,S=d++;return function(A){function M(A,M,t){var I=B(A,M,t);return I}var t="Connect("+T(A)+")",I=function(I){function T(A,M){g(this,T);var i=e(this,I.call(this,A,M));i.version=S,i.store=A.store||M.store,(0,u.default)(i.store,'Could not find "store" in either the context or '+('props of "'+t+'". ')+"Either wrap the root component in a , "+('or explicitly pass "store" as a prop to "'+t+'".'));var E=i.store.getState();return i.state={storeState:E},i.clearCache(),i}return i(T,I),T.prototype.shouldComponentUpdate=function(){return!s||this.haveOwnPropsChanged||this.hasStoreStateChanged},T.prototype.computeStateProps=function(A,M){if(!this.finalMapStateToProps)return this.configureFinalMapState(A,M);var t=A.getState(),I=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(t,M):this.finalMapStateToProps(t);return I},T.prototype.configureFinalMapState=function(A,M){var t=C(A.getState(),M),I="function"==typeof t;return this.finalMapStateToProps=I?t:C,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,I?this.computeStateProps(A,M):t},T.prototype.computeDispatchProps=function(A,M){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(A,M);var t=A.dispatch,I=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(t,M):this.finalMapDispatchToProps(t);return I},T.prototype.configureFinalMapDispatch=function(A,M){var t=D(A.dispatch,M),I="function"==typeof t;return this.finalMapDispatchToProps=I?t:D,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,I?this.computeDispatchProps(A,M):t},T.prototype.updateStatePropsIfNeeded=function(){var A=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,a.default)(A,this.stateProps))&&(this.stateProps=A,!0)},T.prototype.updateDispatchPropsIfNeeded=function(){var A=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,a.default)(A,this.dispatchProps))&&(this.dispatchProps=A,!0)},T.prototype.updateMergedPropsIfNeeded=function(){var A=M(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&h&&(0,a.default)(A,this.mergedProps))&&(this.mergedProps=A,!0)},T.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},T.prototype.trySubscribe=function(){N&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},T.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},T.prototype.componentDidMount=function(){this.trySubscribe()},T.prototype.componentWillReceiveProps=function(A){s&&(0,a.default)(A,this.props)||(this.haveOwnPropsChanged=!0)},T.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},T.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},T.prototype.handleChange=function(){if(this.unsubscribe){var A=this.store.getState(),M=this.state.storeState;if(!s||M!==A){if(s&&!this.doStatePropsDependOnOwnProps){var t=E(this.updateStatePropsIfNeeded,this);if(!t)return;t===Y&&(this.statePropsPrecalculationError=Y.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:A})}}},T.prototype.getWrappedInstance=function(){return(0,u.default)(y,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},T.prototype.render=function(){var M=this.haveOwnPropsChanged,t=this.hasStoreStateChanged,I=this.haveStatePropsBeenPrecalculated,g=this.statePropsPrecalculationError,e=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,g)throw g;var i=!0,T=!0;s&&e&&(i=t||M&&this.doStatePropsDependOnOwnProps,T=M&&this.doDispatchPropsDependOnOwnProps);var E=!1,N=!1;I?E=!0:i&&(E=this.updateStatePropsIfNeeded()),T&&(N=this.updateDispatchPropsIfNeeded());var C=!0;return C=!!(E||N||M)&&this.updateMergedPropsIfNeeded(),!C&&e?e:(y?this.renderedElement=(0,n.createElement)(A,o({},this.mergedProps,{ref:"wrappedInstance"})):this.renderedElement=(0,n.createElement)(A,this.mergedProps),this.renderedElement)},T}(n.Component);return I.displayName=t,I.WrappedComponent=A,I.contextTypes={store:c.default},I.propTypes={store:c.default},(0,j.default)(I,A)}}M.__esModule=!0;var o=Object.assign||function(A){for(var M=1;M should not have a "'+M+'" prop')}M.__esModule=!0, -M.routes=M.route=M.components=M.component=M.history=void 0,M.falsy=I;var g=t(1),e=g.PropTypes.func,i=g.PropTypes.object,T=g.PropTypes.arrayOf,E=g.PropTypes.oneOfType,N=g.PropTypes.element,o=g.PropTypes.shape,n=g.PropTypes.string,C=(M.history=o({listen:e.isRequired,push:e.isRequired,replace:e.isRequired,go:e.isRequired,goBack:e.isRequired,goForward:e.isRequired}),M.component=E([e,n])),c=(M.components=E([C,i]),M.route=E([i,N]));M.routes=E([c,T(c)])},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){var M=A.match(/^https?:\/\/[^\/]*/);return null==M?A:A.substring(M[0].length)}function e(A){var M=g(A),t="",I="",e=M.indexOf("#");e!==-1&&(I=M.substring(e),M=M.substring(0,e));var i=M.indexOf("?");return i!==-1&&(t=M.substring(i),M=M.substring(0,i)),""===M&&(M="/"),{pathname:M,search:t,hash:I}}M.__esModule=!0,M.extractPath=g,M.parsePath=e;var i=t(23);I(i)},function(A,M,t){"use strict";function I(){g.attachRefs(this,this._currentElement)}var g=t(459),e={mountComponent:function(A,M,t,g){var e=A.mountComponent(M,t,g);return A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A),e},unmountComponent:function(A){g.detachRefs(A,A._currentElement),A.unmountComponent()},receiveComponent:function(A,M,t,e){var i=A._currentElement;if(M!==i||e!==A._context){var T=g.shouldUpdateRefs(i,M);T&&g.detachRefs(A,i),A.receiveComponent(M,t,e),T&&A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A)}},performUpdateIfNecessary:function(A,M){A.performUpdateIfNecessary(M)}};A.exports=e},function(A,M,t){"use strict";function I(A,M,t,I){this.dispatchConfig=A,this.dispatchMarker=M,this.nativeEvent=t;var g=this.constructor.Interface;for(var e in g)if(g.hasOwnProperty(e)){var T=g[e];T?this[e]=T(t):"target"===e?this.target=I:this[e]=t[e]}var E=null!=t.defaultPrevented?t.defaultPrevented:t.returnValue===!1;E?this.isDefaultPrevented=i.thatReturnsTrue:this.isDefaultPrevented=i.thatReturnsFalse,this.isPropagationStopped=i.thatReturnsFalse}var g=t(31),e=t(4),i=t(20),T=(t(3),{type:null,target:null,currentTarget:i.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(A){return A.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null});e(I.prototype,{preventDefault:function(){this.defaultPrevented=!0;var A=this.nativeEvent;A&&(A.preventDefault?A.preventDefault():A.returnValue=!1,this.isDefaultPrevented=i.thatReturnsTrue)},stopPropagation:function(){var A=this.nativeEvent;A&&(A.stopPropagation?A.stopPropagation():A.cancelBubble=!0,this.isPropagationStopped=i.thatReturnsTrue)},persist:function(){this.isPersistent=i.thatReturnsTrue},isPersistent:i.thatReturnsFalse,destructor:function(){var A=this.constructor.Interface;for(var M in A)this[M]=null;this.dispatchConfig=null,this.dispatchMarker=null,this.nativeEvent=null}}),I.Interface=T,I.augmentClass=function(A,M){var t=this,I=Object.create(t.prototype);e(I,A.prototype),A.prototype=I,A.prototype.constructor=A,A.Interface=e({},t.Interface,M),A.augmentClass=t.augmentClass,g.addPoolingTo(A,g.fourArgumentPooler)},g.addPoolingTo(I,g.fourArgumentPooler),A.exports=I},function(A,M){"use strict";M.default=function(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t},M.__esModule=!0},function(A,M){"use strict";function t(A){return A&&A.ownerDocument||document}M.__esModule=!0,M.default=t,A.exports=M.default},function(A,M,t){"use strict";var I=t(32),g=function(){var A=I&&document.documentElement;return A&&A.contains?function(A,M){return A.contains(M)}:A&&A.compareDocumentPosition?function(A,M){return A===M||!!(16&A.compareDocumentPosition(M))}:function(A,M){if(M)do if(M===A)return!0;while(M=M.parentNode);return!1}}();A.exports=g},function(A,M){function t(A){return"number"==typeof A&&A>-1&&A%1==0&&A<=I}var I=9007199254740991;A.exports=t},function(A,M,t){(function(A){!function(M,t){A.exports=t()}(this,function(){"use strict";function M(){return aI.apply(null,arguments)}function t(A){aI=A}function I(A){return A instanceof Array||"[object Array]"===Object.prototype.toString.call(A)}function g(A){return null!=A&&"[object Object]"===Object.prototype.toString.call(A)}function e(A){var M;for(M in A)return!1;return!0}function i(A){return"number"==typeof A||"[object Number]"===Object.prototype.toString.call(A)}function T(A){return A instanceof Date||"[object Date]"===Object.prototype.toString.call(A)}function E(A,M){var t,I=[];for(t=0;t0)for(t in rI)I=rI[t],g=M[I],B(g)||(A[I]=g);return A}function r(A){Q(this,A),this._d=new Date(null!=A._d?A._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),sI===!1&&(sI=!0,M.updateOffset(this),sI=!1)}function s(A){return A instanceof r||null!=A&&null!=A._isAMomentObject}function x(A){return A<0?Math.ceil(A)||0:Math.floor(A)}function j(A){var M=+A,t=0;return 0!==M&&isFinite(M)&&(t=x(M)),t}function y(A,M,t){var I,g=Math.min(A.length,M.length),e=Math.abs(A.length-M.length),i=0;for(I=0;I0?"future":"past"];return l(t)?t(M):t.replace(/%s/i,M)}function F(A,M){var t=A.toLowerCase();SI[t]=SI[t+"s"]=SI[M]=A}function f(A){return"string"==typeof A?SI[A]||SI[A.toLowerCase()]:void 0}function k(A){var M,t,I={};for(t in A)N(A,t)&&(M=f(t),M&&(I[M]=A[t]));return I}function R(A,M){zI[A]=M}function J(A){var M=[];for(var t in A)M.push({unit:t,priority:zI[t]});return M.sort(function(A,M){return A.priority-M.priority}),M}function G(A,t){return function(I){return null!=I?(b(this,A,I),M.updateOffset(this,t),this):H(this,A)}}function H(A,M){return A.isValid()?A._d["get"+(A._isUTC?"UTC":"")+M]():NaN}function b(A,M,t){A.isValid()&&A._d["set"+(A._isUTC?"UTC":"")+M](t)}function X(A){return A=f(A),l(this[A])?this[A]():this}function v(A,M){if("object"==typeof A){A=k(A);for(var t=J(A),I=0;I=0;return(e?t?"+":"":"-")+Math.pow(10,Math.max(0,g)).toString().substr(1)+I}function V(A,M,t,I){var g=I;"string"==typeof I&&(g=function(){return this[I]()}),A&&(mI[A]=g),M&&(mI[M[0]]=function(){return W(g.apply(this,arguments),M[1],M[2])}),t&&(mI[t]=function(){return this.localeData().ordinal(g.apply(this,arguments),A)})}function P(A){return A.match(/\[[\s\S]/)?A.replace(/^\[|\]$/g,""):A.replace(/\\/g,"")}function Z(A){var M,t,I=A.match(pI);for(M=0,t=I.length;M=0&&UI.test(A);)A=A.replace(UI,t),UI.lastIndex=0,I-=1;return A}function _(A,M,t){$I[A]=l(M)?M:function(A,I){return A&&t?t:M}}function $(A,M){return N($I,A)?$I[A](M._strict,M._locale):new RegExp(AA(A))}function AA(A){return MA(A.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(A,M,t,I,g){return M||t||I||g}))}function MA(A){return A.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function tA(A,M){var t,I=M;for("string"==typeof A&&(A=[A]),i(M)&&(I=function(A,t){t[M]=j(A)}),t=0;t=0&&isFinite(T.getFullYear())&&T.setFullYear(A),T}function xA(A){var M=new Date(Date.UTC.apply(null,arguments));return A<100&&A>=0&&isFinite(M.getUTCFullYear())&&M.setUTCFullYear(A),M}function jA(A,M,t){var I=7+M-t,g=(7+xA(A,0,I).getUTCDay()-M)%7;return-g+I-1}function yA(A,M,t,I,g){var e,i,T=(7+t-I)%7,E=jA(A,I,g),N=1+7*(M-1)+T+E;return N<=0?(e=A-1,i=BA(e)+N):N>BA(A)?(e=A+1,i=N-BA(A)):(e=A,i=N),{year:e,dayOfYear:i}}function uA(A,M,t){var I,g,e=jA(A.year(),M,t),i=Math.floor((A.dayOfYear()-e-1)/7)+1;return i<1?(g=A.year()-1,I=i+wA(g,M,t)):i>wA(A.year(),M,t)?(I=i-wA(A.year(),M,t),g=A.year()+1):(g=A.year(),I=i),{week:I,year:g}}function wA(A,M,t){var I=jA(A,M,t),g=jA(A+1,M,t);return(BA(A)-I+g)/7}function LA(A){return uA(A,this._week.dow,this._week.doy).week}function lA(){return this._week.dow}function YA(){return this._week.doy}function dA(A){var M=this.localeData().week(this);return null==A?M:this.add(7*(A-M),"d")}function hA(A){var M=uA(this,1,4).week;return null==A?M:this.add(7*(A-M),"d")}function SA(A,M){return"string"!=typeof A?A:isNaN(A)?(A=M.weekdaysParse(A),"number"==typeof A?A:null):parseInt(A,10)}function zA(A,M){return"string"==typeof A?M.weekdaysParse(A)%7||7:isNaN(A)?null:A}function pA(A,M){return A?I(this._weekdays)?this._weekdays[A.day()]:this._weekdays[this._weekdays.isFormat.test(M)?"format":"standalone"][A.day()]:this._weekdays}function UA(A){return A?this._weekdaysShort[A.day()]:this._weekdaysShort}function OA(A){return A?this._weekdaysMin[A.day()]:this._weekdaysMin}function mA(A,M,t){var I,g,e,i=A.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],I=0;I<7;++I)e=n([2e3,1]).day(I),this._minWeekdaysParse[I]=this.weekdaysMin(e,"").toLocaleLowerCase(),this._shortWeekdaysParse[I]=this.weekdaysShort(e,"").toLocaleLowerCase(),this._weekdaysParse[I]=this.weekdays(e,"").toLocaleLowerCase();return t?"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:null):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null):"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null)))}function FA(A,M,t){var I,g,e;if(this._weekdaysParseExact)return mA.call(this,A,M,t);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),I=0;I<7;I++){if(g=n([2e3,1]).day(I),t&&!this._fullWeekdaysParse[I]&&(this._fullWeekdaysParse[I]=new RegExp("^"+this.weekdays(g,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[I]=new RegExp("^"+this.weekdaysShort(g,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[I]=new RegExp("^"+this.weekdaysMin(g,"").replace(".",".?")+"$","i")),this._weekdaysParse[I]||(e="^"+this.weekdays(g,"")+"|^"+this.weekdaysShort(g,"")+"|^"+this.weekdaysMin(g,""),this._weekdaysParse[I]=new RegExp(e.replace(".",""),"i")),t&&"dddd"===M&&this._fullWeekdaysParse[I].test(A))return I;if(t&&"ddd"===M&&this._shortWeekdaysParse[I].test(A))return I;if(t&&"dd"===M&&this._minWeekdaysParse[I].test(A))return I;if(!t&&this._weekdaysParse[I].test(A))return I}}function fA(A){if(!this.isValid())return null!=A?this:NaN;var M=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=A?(A=SA(A,this.localeData()),this.add(A-M,"d")):M}function kA(A){if(!this.isValid())return null!=A?this:NaN;var M=(this.day()+7-this.localeData()._week.dow)%7;return null==A?M:this.add(A-M,"d")}function RA(A){if(!this.isValid())return null!=A?this:NaN;if(null!=A){var M=zA(A,this.localeData());return this.day(this.day()%7?M:M-7)}return this.day()||7}function JA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysStrictRegex:this._weekdaysRegex):(N(this,"_weekdaysRegex")||(this._weekdaysRegex=jg),this._weekdaysStrictRegex&&A?this._weekdaysStrictRegex:this._weekdaysRegex)}function GA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(N(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=yg),this._weekdaysShortStrictRegex&&A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function HA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(N(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=ug),this._weekdaysMinStrictRegex&&A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function bA(){function A(A,M){return M.length-A.length}var M,t,I,g,e,i=[],T=[],E=[],N=[];for(M=0;M<7;M++)t=n([2e3,1]).day(M),I=this.weekdaysMin(t,""),g=this.weekdaysShort(t,""),e=this.weekdays(t,""),i.push(I),T.push(g),E.push(e),N.push(I),N.push(g),N.push(e);for(i.sort(A),T.sort(A),E.sort(A),N.sort(A),M=0;M<7;M++)T[M]=MA(T[M]),E[M]=MA(E[M]),N[M]=MA(N[M]);this._weekdaysRegex=new RegExp("^("+N.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+E.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+T.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function XA(){return this.hours()%12||12}function vA(){return this.hours()||24}function WA(A,M){V(A,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),M)})}function VA(A,M){return M._meridiemParse}function PA(A){return"p"===(A+"").toLowerCase().charAt(0)}function ZA(A,M,t){return A>11?t?"pm":"PM":t?"am":"AM"}function KA(A){return A?A.toLowerCase().replace("_","-"):A}function qA(A){for(var M,t,I,g,e=0;e0;){if(I=_A(g.slice(0,M).join("-")))return I;if(t&&t.length>=M&&y(g,t,!0)>=M-1)break;M--}e++}return null}function _A(M){var t=null;if(!dg[M]&&"undefined"!=typeof A&&A&&A.exports)try{t=wg._abbr,!function(){var A=new Error('Cannot find module "./locale"');throw A.code="MODULE_NOT_FOUND",A}(),$A(t)}catch(A){}return dg[M]}function $A(A,M){var t;return A&&(t=B(M)?tM(A):AM(A,M),t&&(wg=t)),wg._abbr}function AM(A,M){if(null!==M){var t=Yg;if(M.abbr=A,null!=dg[A])L("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),t=dg[A]._config;else if(null!=M.parentLocale){if(null==dg[M.parentLocale])return hg[M.parentLocale]||(hg[M.parentLocale]=[]),hg[M.parentLocale].push({name:A,config:M}),null;t=dg[M.parentLocale]._config}return dg[A]=new h(d(t,M)),hg[A]&&hg[A].forEach(function(A){AM(A.name,A.config)}),$A(A),dg[A]}return delete dg[A],null}function MM(A,M){if(null!=M){var t,I=Yg;null!=dg[A]&&(I=dg[A]._config),M=d(I,M),t=new h(M),t.parentLocale=dg[A],dg[A]=t,$A(A)}else null!=dg[A]&&(null!=dg[A].parentLocale?dg[A]=dg[A].parentLocale:null!=dg[A]&&delete dg[A]);return dg[A]}function tM(A){var M;if(A&&A._locale&&A._locale._abbr&&(A=A._locale._abbr),!A)return wg;if(!I(A)){if(M=_A(A))return M;A=[A]}return qA(A)}function IM(){return uI(dg)}function gM(A){var M,t=A._a;return t&&c(A).overflow===-2&&(M=t[tg]<0||t[tg]>11?tg:t[Ig]<1||t[Ig]>eA(t[Mg],t[tg])?Ig:t[gg]<0||t[gg]>24||24===t[gg]&&(0!==t[eg]||0!==t[ig]||0!==t[Tg])?gg:t[eg]<0||t[eg]>59?eg:t[ig]<0||t[ig]>59?ig:t[Tg]<0||t[Tg]>999?Tg:-1,c(A)._overflowDayOfYear&&(MIg)&&(M=Ig),c(A)._overflowWeeks&&M===-1&&(M=Eg),c(A)._overflowWeekday&&M===-1&&(M=Ng),c(A).overflow=M),A}function eM(A){var M,t,I,g,e,i,T=A._i,E=Sg.exec(T)||zg.exec(T);if(E){for(c(A).iso=!0,M=0,t=Ug.length;MBA(g)&&(c(A)._overflowDayOfYear=!0),t=xA(g,0,A._dayOfYear),A._a[tg]=t.getUTCMonth(),A._a[Ig]=t.getUTCDate()),M=0;M<3&&null==A._a[M];++M)A._a[M]=e[M]=I[M];for(;M<7;M++)A._a[M]=e[M]=null==A._a[M]?2===M?1:0:A._a[M];24===A._a[gg]&&0===A._a[eg]&&0===A._a[ig]&&0===A._a[Tg]&&(A._nextDay=!0,A._a[gg]=0),A._d=(A._useUTC?xA:sA).apply(null,e),null!=A._tzm&&A._d.setUTCMinutes(A._d.getUTCMinutes()-A._tzm),A._nextDay&&(A._a[gg]=24)}}function oM(A){var M,t,I,g,e,i,T,E;if(M=A._w,null!=M.GG||null!=M.W||null!=M.E)e=1,i=4,t=TM(M.GG,A._a[Mg],uA(sM(),1,4).year),I=TM(M.W,1),g=TM(M.E,1),(g<1||g>7)&&(E=!0);else{e=A._locale._week.dow,i=A._locale._week.doy;var N=uA(sM(),e,i);t=TM(M.gg,A._a[Mg],N.year),I=TM(M.w,N.week),null!=M.d?(g=M.d,(g<0||g>6)&&(E=!0)):null!=M.e?(g=M.e+e,(M.e<0||M.e>6)&&(E=!0)):g=e}I<1||I>wA(t,e,i)?c(A)._overflowWeeks=!0:null!=E?c(A)._overflowWeekday=!0:(T=yA(t,I,g,e,i),A._a[Mg]=T.year,A._dayOfYear=T.dayOfYear)}function nM(A){if(A._f===M.ISO_8601)return void eM(A);A._a=[],c(A).empty=!0;var t,I,g,e,i,T=""+A._i,E=T.length,N=0;for(g=q(A._f,A._locale).match(pI)||[],t=0;t0&&c(A).unusedInput.push(i),T=T.slice(T.indexOf(I)+I.length),N+=I.length),mI[e]?(I?c(A).empty=!1:c(A).unusedTokens.push(e),gA(e,I,A)):A._strict&&!I&&c(A).unusedTokens.push(e);c(A).charsLeftOver=E-N,T.length>0&&c(A).unusedInput.push(T),A._a[gg]<=12&&c(A).bigHour===!0&&A._a[gg]>0&&(c(A).bigHour=void 0),c(A).parsedDateParts=A._a.slice(0),c(A).meridiem=A._meridiem,A._a[gg]=CM(A._locale,A._a[gg],A._meridiem),NM(A),gM(A)}function CM(A,M,t){var I;return null==t?M:null!=A.meridiemHour?A.meridiemHour(M,t):null!=A.isPM?(I=A.isPM(t),I&&M<12&&(M+=12),I||12!==M||(M=0),M):M}function cM(A){var M,t,I,g,e;if(0===A._f.length)return c(A).invalidFormat=!0,void(A._d=new Date(NaN));for(g=0;gthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function fM(){if(!B(this._isDSTShifted))return this._isDSTShifted;var A={};if(Q(A,this),A=BM(A),A._a){var M=A._isUTC?n(A._a):sM(A._a);this._isDSTShifted=this.isValid()&&y(A._a,M.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function kM(){return!!this.isValid()&&!this._isUTC}function RM(){return!!this.isValid()&&this._isUTC}function JM(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function GM(A,M){var t,I,g,e=A,T=null;return wM(A)?e={ms:A._milliseconds,d:A._days,M:A._months}:i(A)?(e={},M?e[M]=A:e.milliseconds=A):(T=Jg.exec(A))?(t="-"===T[1]?-1:1,e={y:0,d:j(T[Ig])*t,h:j(T[gg])*t,m:j(T[eg])*t,s:j(T[ig])*t,ms:j(LM(1e3*T[Tg]))*t}):(T=Gg.exec(A))?(t="-"===T[1]?-1:1,e={y:HM(T[2],t),M:HM(T[3],t),w:HM(T[4],t),d:HM(T[5],t),h:HM(T[6],t),m:HM(T[7],t),s:HM(T[8],t)}):null==e?e={}:"object"==typeof e&&("from"in e||"to"in e)&&(g=XM(sM(e.from),sM(e.to)),e={},e.ms=g.milliseconds,e.M=g.months),I=new uM(e),wM(A)&&N(A,"_locale")&&(I._locale=A._locale),I}function HM(A,M){var t=A&&parseFloat(A.replace(",","."));return(isNaN(t)?0:t)*M}function bM(A,M){var t={milliseconds:0,months:0};return t.months=M.month()-A.month()+12*(M.year()-A.year()),A.clone().add(t.months,"M").isAfter(M)&&--t.months,t.milliseconds=+M-+A.clone().add(t.months,"M"),t}function XM(A,M){var t;return A.isValid()&&M.isValid()?(M=dM(M,A),A.isBefore(M)?t=bM(A,M):(t=bM(M,A),t.milliseconds=-t.milliseconds,t.months=-t.months),t):{milliseconds:0,months:0}}function vM(A,M){return function(t,I){var g,e;return null===I||isNaN(+I)||(L(M,"moment()."+M+"(period, number) is deprecated. Please use moment()."+M+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),e=t,t=I,I=e),t="string"==typeof t?+t:t,g=GM(t,I),WM(this,g,A),this}}function WM(A,t,I,g){var e=t._milliseconds,i=LM(t._days),T=LM(t._months);A.isValid()&&(g=null==g||g,e&&A._d.setTime(A._d.valueOf()+e*I),i&&b(A,"Date",H(A,"Date")+i*I),T&&oA(A,H(A,"Month")+T*I),g&&M.updateOffset(A,i||T))}function VM(A,M){var t=A.diff(M,"days",!0);return t<-6?"sameElse":t<-1?"lastWeek":t<0?"lastDay":t<1?"sameDay":t<2?"nextDay":t<7?"nextWeek":"sameElse"}function PM(A,t){var I=A||sM(),g=dM(I,this).startOf("day"),e=M.calendarFormat(this,g)||"sameElse",i=t&&(l(t[e])?t[e].call(this,I):t[e]);return this.format(i||this.localeData().calendar(e,this,sM(I)))}function ZM(){return new r(this)}function KM(A,M){var t=s(A)?A:sM(A);return!(!this.isValid()||!t.isValid())&&(M=f(B(M)?"millisecond":M),"millisecond"===M?this.valueOf()>t.valueOf():t.valueOf()e&&(M=e),pt.call(this,A,M,t,I,g))}function pt(A,M,t,I,g){var e=yA(A,M,t,I,g),i=xA(e.year,0,e.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}function Ut(A){return null==A?Math.ceil((this.month()+1)/3):this.month(3*(A-1)+this.month()%3)}function Ot(A){var M=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==A?M:this.add(A-M,"d")}function mt(A,M){M[Tg]=j(1e3*("0."+A))}function Ft(){return this._isUTC?"UTC":""}function ft(){return this._isUTC?"Coordinated Universal Time":""}function kt(A){return sM(1e3*A)}function Rt(){return sM.apply(null,arguments).parseZone()}function Jt(A){return A}function Gt(A,M,t,I){var g=tM(),e=n().set(I,M);return g[t](e,A)}function Ht(A,M,t){if(i(A)&&(M=A,A=void 0),A=A||"",null!=M)return Gt(A,M,t,"month");var I,g=[];for(I=0;I<12;I++)g[I]=Gt(A,I,t,"month");return g}function bt(A,M,t,I){"boolean"==typeof A?(i(M)&&(t=M,M=void 0),M=M||""):(M=A,t=M,A=!1,i(M)&&(t=M,M=void 0),M=M||"");var g=tM(),e=A?g._week.dow:0;if(null!=t)return Gt(M,(t+e)%7,I,"day");var T,E=[];for(T=0;T<7;T++)E[T]=Gt(M,(T+e)%7,I,"day");return E}function Xt(A,M){return Ht(A,M,"months")}function vt(A,M){return Ht(A,M,"monthsShort")}function Wt(A,M,t){return bt(A,M,t,"weekdays")}function Vt(A,M,t){return bt(A,M,t,"weekdaysShort")}function Pt(A,M,t){return bt(A,M,t,"weekdaysMin")}function Zt(){var A=this._data;return this._milliseconds=_g(this._milliseconds),this._days=_g(this._days),this._months=_g(this._months),A.milliseconds=_g(A.milliseconds),A.seconds=_g(A.seconds),A.minutes=_g(A.minutes),A.hours=_g(A.hours),A.months=_g(A.months),A.years=_g(A.years),this}function Kt(A,M,t,I){var g=GM(M,t);return A._milliseconds+=I*g._milliseconds,A._days+=I*g._days,A._months+=I*g._months,A._bubble()}function qt(A,M){return Kt(this,A,M,1)}function _t(A,M){return Kt(this,A,M,-1)}function $t(A){return A<0?Math.floor(A):Math.ceil(A)}function AI(){var A,M,t,I,g,e=this._milliseconds,i=this._days,T=this._months,E=this._data;return e>=0&&i>=0&&T>=0||e<=0&&i<=0&&T<=0||(e+=864e5*$t(tI(T)+i),i=0,T=0),E.milliseconds=e%1e3,A=x(e/1e3),E.seconds=A%60,M=x(A/60),E.minutes=M%60,t=x(M/60),E.hours=t%24,i+=x(t/24),g=x(MI(i)),T+=g,i-=$t(tI(g)),I=x(T/12),T%=12,E.days=i,E.months=T,E.years=I,this}function MI(A){return 4800*A/146097}function tI(A){return 146097*A/4800}function II(A){var M,t,I=this._milliseconds;if(A=f(A),"month"===A||"year"===A)return M=this._days+I/864e5,t=this._months+MI(M),"month"===A?t:t/12;switch(M=this._days+Math.round(tI(this._months)),A){case"week":return M/7+I/6048e5;case"day":return M+I/864e5;case"hour":return 24*M+I/36e5;case"minute":return 1440*M+I/6e4;case"second":return 86400*M+I/1e3;case"millisecond":return Math.floor(864e5*M)+I;default:throw new Error("Unknown unit "+A)}}function gI(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*j(this._months/12)}function eI(A){return function(){return this.as(A)}}function iI(A){return A=f(A),this[A+"s"]()}function TI(A){return function(){return this._data[A]}}function EI(){return x(this.days()/7)}function NI(A,M,t,I,g){return g.relativeTime(M||1,!!t,A,I)}function oI(A,M,t){var I=GM(A).abs(),g=De(I.as("s")),e=De(I.as("m")),i=De(I.as("h")),T=De(I.as("d")),E=De(I.as("M")),N=De(I.as("y")),o=g0,o[4]=t,NI.apply(null,o)}function nI(A){return void 0===A?De:"function"==typeof A&&(De=A,!0)}function CI(A,M){return void 0!==ae[A]&&(void 0===M?ae[A]:(ae[A]=M,!0))}function cI(A){var M=this.localeData(),t=oI(this,!A,M);return A&&(t=M.pastFuture(+this,t)),M.postformat(t)}function DI(){var A,M,t,I=Be(this._milliseconds)/1e3,g=Be(this._days),e=Be(this._months);A=x(I/60),M=x(A/60),I%=60,A%=60,t=x(e/12),e%=12;var i=t,T=e,E=g,N=M,o=A,n=I,C=this.asSeconds();return C?(C<0?"-":"")+"P"+(i?i+"Y":"")+(T?T+"M":"")+(E?E+"D":"")+(N||o||n?"T":"")+(N?N+"H":"")+(o?o+"M":"")+(n?n+"S":""):"P0D"}var aI,BI;BI=Array.prototype.some?Array.prototype.some:function(A){for(var M=Object(this),t=M.length>>>0,I=0;I68?1900:2e3)};var Bg=G("FullYear",!0);V("w",["ww",2],"wo","week"),V("W",["WW",2],"Wo","isoWeek"),F("week","w"),F("isoWeek","W"),R("week",5),R("isoWeek",5),_("w",GI),_("ww",GI,fI),_("W",GI),_("WW",GI,fI),IA(["w","ww","W","WW"],function(A,M,t,I){M[I.substr(0,1)]=j(A)});var Qg={dow:0,doy:6};V("d",0,"do","day"),V("dd",0,0,function(A){return this.localeData().weekdaysMin(this,A)}),V("ddd",0,0,function(A){return this.localeData().weekdaysShort(this,A)}),V("dddd",0,0,function(A){return this.localeData().weekdays(this,A)}),V("e",0,0,"weekday"),V("E",0,0,"isoWeekday"),F("day","d"),F("weekday","e"),F("isoWeekday","E"),R("day",11),R("weekday",11),R("isoWeekday",11),_("d",GI),_("e",GI),_("E",GI),_("dd",function(A,M){return M.weekdaysMinRegex(A)}),_("ddd",function(A,M){return M.weekdaysShortRegex(A)}),_("dddd",function(A,M){return M.weekdaysRegex(A)}),IA(["dd","ddd","dddd"],function(A,M,t,I){var g=t._locale.weekdaysParse(A,I,t._strict);null!=g?M.d=g:c(t).invalidWeekday=A}),IA(["d","e","E"],function(A,M,t,I){M[I]=j(A)});var rg="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),sg="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),xg="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),jg=_I,yg=_I,ug=_I;V("H",["HH",2],0,"hour"),V("h",["hh",2],0,XA),V("k",["kk",2],0,vA),V("hmm",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)}),V("hmmss",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)+W(this.seconds(),2)}),V("Hmm",0,0,function(){return""+this.hours()+W(this.minutes(),2)}),V("Hmmss",0,0,function(){return""+this.hours()+W(this.minutes(),2)+W(this.seconds(),2)}),WA("a",!0),WA("A",!1),F("hour","h"),R("hour",13),_("a",VA),_("A",VA),_("H",GI),_("h",GI),_("HH",GI,fI),_("hh",GI,fI),_("hmm",HI),_("hmmss",bI),_("Hmm",HI),_("Hmmss",bI),tA(["H","HH"],gg),tA(["a","A"],function(A,M,t){t._isPm=t._locale.isPM(A),t._meridiem=A}),tA(["h","hh"],function(A,M,t){M[gg]=j(A),c(t).bigHour=!0}),tA("hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I)),c(t).bigHour=!0}),tA("hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g)),c(t).bigHour=!0}),tA("Hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I))}),tA("Hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g))});var wg,Lg=/[ap]\.?m?\.?/i,lg=G("Hours",!0),Yg={calendar:wI,longDateFormat:LI,invalidDate:lI,ordinal:YI,ordinalParse:dI,relativeTime:hI,months:Cg,monthsShort:cg,week:Qg,weekdays:rg,weekdaysMin:xg,weekdaysShort:sg,meridiemParse:Lg},dg={},hg={},Sg=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,zg=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,pg=/Z|[+-]\d\d(?::?\d\d)?/,Ug=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Og=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],mg=/^\/?Date\((\-?\d+)/i;M.createFromInputFallback=w("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(A){A._d=new Date(A._i+(A._useUTC?" UTC":""))}),M.ISO_8601=function(){};var Fg=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var A=sM.apply(null,arguments);return this.isValid()&&A.isValid()?Athis?this:A:a()}),kg=function(){return Date.now?Date.now():+new Date};lM("Z",":"),lM("ZZ",""),_("Z",KI),_("ZZ",KI),tA(["Z","ZZ"],function(A,M,t){t._useUTC=!0,t._tzm=YM(KI,A)});var Rg=/([\+\-]|\d\d)/gi;M.updateOffset=function(){};var Jg=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Gg=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;GM.fn=uM.prototype;var Hg=vM(1,"add"),bg=vM(-1,"subtract");M.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",M.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xg=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(A){return void 0===A?this.localeData():this.locale(A)});V(0,["gg",2],0,function(){return this.weekYear()%100}),V(0,["GG",2],0,function(){return this.isoWeekYear()%100}),lt("gggg","weekYear"),lt("ggggg","weekYear"),lt("GGGG","isoWeekYear"),lt("GGGGG","isoWeekYear"),F("weekYear","gg"),F("isoWeekYear","GG"),R("weekYear",1),R("isoWeekYear",1),_("G",PI),_("g",PI),_("GG",GI,fI),_("gg",GI,fI),_("GGGG",vI,RI),_("gggg",vI,RI),_("GGGGG",WI,JI),_("ggggg",WI,JI),IA(["gggg","ggggg","GGGG","GGGGG"],function(A,M,t,I){M[I.substr(0,2)]=j(A)}),IA(["gg","GG"],function(A,t,I,g){t[g]=M.parseTwoDigitYear(A)}),V("Q",0,"Qo","quarter"),F("quarter","Q"),R("quarter",7),_("Q",FI),tA("Q",function(A,M){M[tg]=3*(j(A)-1)}),V("D",["DD",2],"Do","date"),F("date","D"),R("date",9),_("D",GI),_("DD",GI,fI),_("Do",function(A,M){return A?M._ordinalParse:M._ordinalParseLenient}),tA(["D","DD"],Ig),tA("Do",function(A,M){M[Ig]=j(A.match(GI)[0],10)});var vg=G("Date",!0);V("DDD",["DDDD",3],"DDDo","dayOfYear"),F("dayOfYear","DDD"),R("dayOfYear",4),_("DDD",XI),_("DDDD",kI),tA(["DDD","DDDD"],function(A,M,t){t._dayOfYear=j(A)}),V("m",["mm",2],0,"minute"),F("minute","m"),R("minute",14),_("m",GI),_("mm",GI,fI),tA(["m","mm"],eg);var Wg=G("Minutes",!1);V("s",["ss",2],0,"second"),F("second","s"),R("second",15),_("s",GI),_("ss",GI,fI),tA(["s","ss"],ig);var Vg=G("Seconds",!1);V("S",0,0,function(){return~~(this.millisecond()/100)}),V(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),V(0,["SSS",3],0,"millisecond"),V(0,["SSSS",4],0,function(){return 10*this.millisecond()}),V(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),V(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),V(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),V(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),V(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),F("millisecond","ms"),R("millisecond",16),_("S",XI,FI),_("SS",XI,fI),_("SSS",XI,kI);var Pg;for(Pg="SSSS";Pg.length<=9;Pg+="S")_(Pg,VI);for(Pg="S";Pg.length<=9;Pg+="S")tA(Pg,mt);var Zg=G("Milliseconds",!1);V("z",0,0,"zoneAbbr"),V("zz",0,0,"zoneName");var Kg=r.prototype;Kg.add=Hg,Kg.calendar=PM,Kg.clone=ZM,Kg.diff=tt,Kg.endOf=at,Kg.format=Tt,Kg.from=Et,Kg.fromNow=Nt,Kg.to=ot,Kg.toNow=nt,Kg.get=X,Kg.invalidAt=wt,Kg.isAfter=KM,Kg.isBefore=qM,Kg.isBetween=_M,Kg.isSame=$M,Kg.isSameOrAfter=At,Kg.isSameOrBefore=Mt,Kg.isValid=yt,Kg.lang=Xg,Kg.locale=Ct,Kg.localeData=ct,Kg.max=fg,Kg.min=Fg,Kg.parsingFlags=ut,Kg.set=v,Kg.startOf=Dt,Kg.subtract=bg,Kg.toArray=st,Kg.toObject=xt,Kg.toDate=rt,Kg.toISOString=et,Kg.inspect=it,Kg.toJSON=jt,Kg.toString=gt,Kg.unix=Qt,Kg.valueOf=Bt,Kg.creationData=Lt,Kg.year=Bg,Kg.isLeapYear=rA,Kg.weekYear=Yt,Kg.isoWeekYear=dt,Kg.quarter=Kg.quarters=Ut,Kg.month=nA,Kg.daysInMonth=CA,Kg.week=Kg.weeks=dA,Kg.isoWeek=Kg.isoWeeks=hA,Kg.weeksInYear=St,Kg.isoWeeksInYear=ht,Kg.date=vg,Kg.day=Kg.days=fA,Kg.weekday=kA,Kg.isoWeekday=RA,Kg.dayOfYear=Ot,Kg.hour=Kg.hours=lg,Kg.minute=Kg.minutes=Wg,Kg.second=Kg.seconds=Vg,Kg.millisecond=Kg.milliseconds=Zg,Kg.utcOffset=SM,Kg.utc=pM,Kg.local=UM,Kg.parseZone=OM,Kg.hasAlignedHourOffset=mM,Kg.isDST=FM,Kg.isLocal=kM,Kg.isUtcOffset=RM,Kg.isUtc=JM,Kg.isUTC=JM,Kg.zoneAbbr=Ft,Kg.zoneName=ft,Kg.dates=w("dates accessor is deprecated. Use date instead.",vg),Kg.months=w("months accessor is deprecated. Use month instead",nA),Kg.years=w("years accessor is deprecated. Use year instead",Bg),Kg.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",zM),Kg.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",fM);var qg=h.prototype;qg.calendar=S,qg.longDateFormat=z,qg.invalidDate=p,qg.ordinal=U,qg.preparse=Jt,qg.postformat=Jt,qg.relativeTime=O,qg.pastFuture=m,qg.set=Y,qg.months=iA,qg.monthsShort=TA,qg.monthsParse=NA,qg.monthsRegex=DA,qg.monthsShortRegex=cA,qg.week=LA,qg.firstDayOfYear=YA,qg.firstDayOfWeek=lA,qg.weekdays=pA,qg.weekdaysMin=OA,qg.weekdaysShort=UA,qg.weekdaysParse=FA,qg.weekdaysRegex=JA,qg.weekdaysShortRegex=GA,qg.weekdaysMinRegex=HA,qg.isPM=PA,qg.meridiem=ZA,$A("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(A){var M=A%10,t=1===j(A%100/10)?"th":1===M?"st":2===M?"nd":3===M?"rd":"th";return A+t}}),M.lang=w("moment.lang is deprecated. Use moment.locale instead.",$A),M.langData=w("moment.langData is deprecated. Use moment.localeData instead.",tM);var _g=Math.abs,$g=eI("ms"),Ae=eI("s"),Me=eI("m"),te=eI("h"),Ie=eI("d"),ge=eI("w"),ee=eI("M"),ie=eI("y"),Te=TI("milliseconds"),Ee=TI("seconds"),Ne=TI("minutes"),oe=TI("hours"),ne=TI("days"),Ce=TI("months"),ce=TI("years"),De=Math.round,ae={s:45,m:45,h:22,d:26,M:11},Be=Math.abs,Qe=uM.prototype;return Qe.abs=Zt,Qe.add=qt,Qe.subtract=_t,Qe.as=II,Qe.asMilliseconds=$g,Qe.asSeconds=Ae,Qe.asMinutes=Me,Qe.asHours=te,Qe.asDays=Ie,Qe.asWeeks=ge,Qe.asMonths=ee,Qe.asYears=ie,Qe.valueOf=gI,Qe._bubble=AI,Qe.get=iI,Qe.milliseconds=Te,Qe.seconds=Ee,Qe.minutes=Ne,Qe.hours=oe,Qe.days=ne,Qe.weeks=EI,Qe.months=Ce,Qe.years=ce,Qe.humanize=cI,Qe.toISOString=DI,Qe.toString=DI,Qe.toJSON=DI,Qe.locale=Ct,Qe.localeData=ct,Qe.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",DI),Qe.lang=Xg,V("X",0,0,"unix"),V("x",0,0,"valueOf"),_("x",PI),_("X",qI),tA("X",function(A,M,t){t._d=new Date(1e3*parseFloat(A,10))}),tA("x",function(A,M,t){t._d=new Date(j(A))}),M.version="2.17.1",t(sM),M.fn=Kg,M.min=jM,M.max=yM,M.now=kg,M.utc=n,M.unix=kt,M.months=Xt,M.isDate=T,M.locale=$A,M.invalid=a,M.duration=GM,M.isMoment=s,M.weekdays=Wt,M.parseZone=Rt,M.localeData=tM,M.isDuration=wM,M.monthsShort=vt,M.weekdaysMin=Pt,M.defineLocale=AM,M.updateLocale=MM,M.locales=IM,M.weekdaysShort=Vt,M.normalizeUnits=f,M.relativeTimeRounding=nI,M.relativeTimeThreshold=CI,M.calendarFormat=VM,M.prototype=Kg,M})}).call(M,t(128)(A))},function(A,M,t){"use strict";var I=t(132).default,g=t(133).default,e=t(78).default;M.__esModule=!0;var i=function(A){return I(g({values:function(){var A=this;return e(this).map(function(M){return A[M]})}}),A)},T={SIZES:{large:"lg",medium:"md",small:"sm",xsmall:"xs",lg:"lg",md:"md",sm:"sm",xs:"xs"},GRID_COLUMNS:12},E=i({LARGE:"large",MEDIUM:"medium",SMALL:"small",XSMALL:"xsmall"});M.Sizes=E;var N=i({SUCCESS:"success",WARNING:"warning",DANGER:"danger",INFO:"info"});M.State=N;var o="default";M.DEFAULT=o;var n="primary";M.PRIMARY=n;var C="link";M.LINK=C;var c="inverse";M.INVERSE=c,M.default=T},function(A,M){"use strict";function t(){for(var A=arguments.length,M=Array(A),t=0;t0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURI(o))):"("===E?g+=1:")"===E?g-=1:":"===E.charAt(0)?(N=E.substring(1),o=M[N],null!=o||g>0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURIComponent(o))):e+=E;return e.replace(/\/+/g,"/")}M.__esModule=!0,M.compilePattern=i,M.matchPattern=T,M.getParamNames=E,M.getParams=N,M.formatPattern=o;var n=t(8),C=I(n),c=Object.create(null)},function(A,M){"use strict";M.__esModule=!0;var t="PUSH";M.PUSH=t;var I="REPLACE";M.REPLACE=I;var g="POP";M.POP=g,M.default={PUSH:t,REPLACE:I,POP:g}},function(A,M,t){"use strict";function I(A,M){return(A&M)===M}var g=t(2),e={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(A){var M=e,t=A.Properties||{},i=A.DOMAttributeNamespaces||{},E=A.DOMAttributeNames||{},N=A.DOMPropertyNames||{},o=A.DOMMutationMethods||{};A.isCustomAttribute&&T._isCustomAttributeFunctions.push(A.isCustomAttribute);for(var n in t){T.properties.hasOwnProperty(n)?g(!1):void 0;var C=n.toLowerCase(),c=t[n],D={attributeName:C,attributeNamespace:null,propertyName:n,mutationMethod:null,mustUseAttribute:I(c,M.MUST_USE_ATTRIBUTE),mustUseProperty:I(c,M.MUST_USE_PROPERTY),hasSideEffects:I(c,M.HAS_SIDE_EFFECTS),hasBooleanValue:I(c,M.HAS_BOOLEAN_VALUE),hasNumericValue:I(c,M.HAS_NUMERIC_VALUE),hasPositiveNumericValue:I(c,M.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:I(c,M.HAS_OVERLOADED_BOOLEAN_VALUE)};if(D.mustUseAttribute&&D.mustUseProperty?g(!1):void 0,!D.mustUseProperty&&D.hasSideEffects?g(!1):void 0,D.hasBooleanValue+D.hasNumericValue+D.hasOverloadedBooleanValue<=1?void 0:g(!1),E.hasOwnProperty(n)){var a=E[n];D.attributeName=a}i.hasOwnProperty(n)&&(D.attributeNamespace=i[n]),N.hasOwnProperty(n)&&(D.propertyName=N[n]),o.hasOwnProperty(n)&&(D.mutationMethod=o[n]),T.properties[n]=D}}},i={},T={ID_ATTRIBUTE_NAME:"data-reactid",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(A){for(var M=0;M1){var M=A.indexOf(c,1);return M>-1?A.substr(0,M):A}return null},traverseEnterLeave:function(A,M,t,I,g){var e=N(A,M);e!==A&&o(A,e,t,I,!1,!0),e!==M&&o(e,M,t,g,!0,!1)},traverseTwoPhase:function(A,M,t){A&&(o("",A,M,t,!0,!1),o(A,"",M,t,!1,!0))},traverseTwoPhaseSkipTarget:function(A,M,t){A&&(o("",A,M,t,!0,!0),o(A,"",M,t,!0,!0))},traverseAncestors:function(A,M,t){o("",A,M,t,!0,!1)},getFirstCommonAncestorID:N,_getNextDescendantID:E,isAncestorIDOf:i,SEPARATOR:c};A.exports=B},function(A,M){var t=A.exports={version:"1.2.6"};"number"==typeof __e&&(__e=t)},function(A,M,t){"use strict";var I={};A.exports=I},function(A,M,t){"use strict";function I(A,M,t){var I=0;return n.default.Children.map(A,function(A){if(n.default.isValidElement(A)){var g=I;return I++,M.call(t,A,g)}return A})}function g(A,M,t){var I=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I),I++)})}function e(A){var M=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&M++}),M}function i(A){var M=!1;return n.default.Children.forEach(A,function(A){!M&&n.default.isValidElement(A)&&(M=!0)}),M}function T(A,M){var t=void 0;return g(A,function(I,g){!t&&M(I,g,A)&&(t=I)}),t}function E(A,M,t){var I=0,g=[];return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I)&&g.push(A),I++)}),g}var N=t(6).default;M.__esModule=!0;var o=t(1),n=N(o);M.default={map:I,forEach:g,numberOf:e,find:T,findValidComponents:E,hasValidComponent:i},A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0}),M.default=function(A){return(0,T.default)(e.default.findDOMNode(A))};var g=t(16),e=I(g),i=t(39),T=I(i);A.exports=M.default},function(A,M,t){"use strict";var I=t(204),g=t(437),e=t(217),i=t(226),T=t(227),E=t(2),N=(t(3),{}),o=null,n=function(A,M){A&&(g.executeDispatchesInOrder(A,M),A.isPersistent()||A.constructor.release(A))},C=function(A){return n(A,!0)},c=function(A){return n(A,!1)},D=null,a={injection:{injectMount:g.injection.injectMount,injectInstanceHandle:function(A){D=A},getInstanceHandle:function(){return D},injectEventPluginOrder:I.injectEventPluginOrder,injectEventPluginsByName:I.injectEventPluginsByName},eventNameDispatchConfigs:I.eventNameDispatchConfigs,registrationNameModules:I.registrationNameModules,putListener:function(A,M,t){"function"!=typeof t?E(!1):void 0;var g=N[M]||(N[M]={});g[A]=t;var e=I.registrationNameModules[M];e&&e.didPutListener&&e.didPutListener(A,M,t)},getListener:function(A,M){var t=N[M];return t&&t[A]},deleteListener:function(A,M){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M);var g=N[M];g&&delete g[A]},deleteAllListeners:function(A){for(var M in N)if(N[M][A]){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M),delete N[M][A]}},extractEvents:function(A,M,t,g,e){for(var T,E=I.plugins,N=0;N1?I-1:0),e=1;e":">","<":"<",'"':""","'":"'"},e=/[&><"']/g;A.exports=I},function(A,M,t){"use strict";var I=t(10),g=/^[ \r\n\t\f]/,e=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,i=function(A,M){A.innerHTML=M};if("undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction&&(i=function(A,M){MSApp.execUnsafeLocalFunction(function(){A.innerHTML=M})}),I.canUseDOM){var T=document.createElement("div");T.innerHTML=" ",""===T.innerHTML&&(i=function(A,M){if(A.parentNode&&A.parentNode.replaceChild(A,A),g.test(M)||"<"===M[0]&&e.test(M)){A.innerHTML=String.fromCharCode(65279)+M;var t=A.firstChild;1===t.data.length?A.removeChild(t):t.deleteData(0,1)}else A.innerHTML=M})}A.exports=i},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=function(A){var M=A.label,t=A.id,I=A.name,g=A.value,i=A.onChange,T=A.type,E=A.spellCheck,N=A.required,o=A.readonly,n=A.autoComplete,C=A.align,c=A.className,D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n});return o&&(D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n,disabled:!0})),e.default.createElement("div",{className:"input-group "+C+" "+c},D,e.default.createElement("i",{className:"ig-helpers"}),e.default.createElement("label",{className:"ig-label"},M))};M.default=i},function(A,M,t){A.exports={default:t(259),__esModule:!0}},function(A,M,t){var I=t(265),g=t(49),e=t(134),i="prototype",T=function(A,M,t){var E,N,o,n=A&T.F,C=A&T.G,c=A&T.S,D=A&T.P,a=A&T.B,B=A&T.W,Q=C?g:g[M]||(g[M]={}),r=C?I:c?I[M]:(I[M]||{})[i];C&&(t=M);for(E in t)N=!n&&r&&E in r,N&&E in Q||(o=N?r[E]:t[E],Q[E]=C&&"function"!=typeof r[E]?t[E]:a&&N?e(o,I):B&&r[E]==o?function(A){var M=function(M){return this instanceof A?new A(M):A(M)};return M[i]=A[i],M}(o):D&&"function"==typeof o?e(Function.call,o):o,D&&((Q[i]||(Q[i]={}))[E]=o))};T.F=1,T.G=2,T.S=4,T.P=8,T.B=16,T.W=32,A.exports=T},function(A,M){var t=Object;A.exports={create:t.create,getProto:t.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:t.getOwnPropertyDescriptor,setDesc:t.defineProperty,setDescs:t.defineProperties,getKeys:t.keys,getNames:t.getOwnPropertyNames,getSymbols:t.getOwnPropertySymbols,each:[].forEach}},function(A,M,t){"use strict";var I=t(32),g=function(){};I&&(g=function(){return document.addEventListener?function(A,M,t,I){return A.addEventListener(M,t,I||!1)}:document.attachEvent?function(A,M,t){return A.attachEvent("on"+M,t)}:void 0}()),A.exports=g},function(A,M,t){"use strict";var I=t(145),g=t(295),e=t(290),i=t(291),T=Object.prototype.hasOwnProperty;A.exports=function(A,M,t){var E="",N=M;if("string"==typeof M){if(void 0===t)return A.style[I(M)]||e(A).getPropertyValue(g(M));(N={})[M]=t}for(var o in N)T.call(N,o)&&(N[o]||0===N[o]?E+=g(o)+":"+N[o]+";":i(A,g(o)));A.style.cssText+=";"+E}},function(A,M,t){(function(){var t=this,I=t.humanize,g={};"undefined"!=typeof A&&A.exports&&(M=A.exports=g),M.humanize=g,g.noConflict=function(){return t.humanize=I,this},g.pad=function(A,M,t,I){if(A+="",t?t.length>1&&(t=t.charAt(0)):t=" ",I=void 0===I?"left":"right","right"===I)for(;A.length4&&A<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th"},w:function(){return t.getDay()},z:function(){return(o.L()?i[o.n()]:e[o.n()])+o.j()-1},W:function(){var A=o.z()-o.N()+1.5;return g.pad(1+Math.floor(Math.abs(A)/7)+(A%7>3.5?1:0),2,"0")},F:function(){return N[t.getMonth()]},m:function(){return g.pad(o.n(),2,"0")},M:function(){return o.F().slice(0,3)},n:function(){return t.getMonth()+1},t:function(){return new Date(o.Y(),o.n(),0).getDate()},L:function(){return 1===new Date(o.Y(),1,29).getMonth()?1:0},o:function(){var A=o.n(),M=o.W();return o.Y()+(12===A&&M<9?-1:1===A&&M>9)},Y:function(){return t.getFullYear()},y:function(){return String(o.Y()).slice(-2)},a:function(){return t.getHours()>11?"pm":"am"},A:function(){return o.a().toUpperCase()},B:function(){var A=t.getTime()/1e3,M=A%86400+3600;M<0&&(M+=86400);var I=M/86.4%1e3;return A<0?Math.ceil(I):Math.floor(I)},g:function(){return o.G()%12||12},G:function(){return t.getHours()},h:function(){return g.pad(o.g(),2,"0")},H:function(){return g.pad(o.G(),2,"0")},i:function(){return g.pad(t.getMinutes(),2,"0")},s:function(){return g.pad(t.getSeconds(),2,"0")},u:function(){return g.pad(1e3*t.getMilliseconds(),6,"0")},O:function(){var A=t.getTimezoneOffset(),M=Math.abs(A);return(A>0?"-":"+")+g.pad(100*Math.floor(M/60)+M%60,4,"0")},P:function(){var A=o.O();return A.substr(0,3)+":"+A.substr(3,2)},Z:function(){return 60*-t.getTimezoneOffset()},c:function(){return"Y-m-d\\TH:i:sP".replace(I,T)},r:function(){return"D, d M Y H:i:s O".replace(I,T)},U:function(){return t.getTime()/1e3||0}};return A.replace(I,T)},g.numberFormat=function(A,M,t,I){M=isNaN(M)?2:Math.abs(M),t=void 0===t?".":t,I=void 0===I?",":I;var g=A<0?"-":"";A=Math.abs(+A||0);var e=parseInt(A.toFixed(M),10)+"",i=e.length>3?e.length%3:0;return g+(i?e.substr(0,i)+I:"")+e.substr(i).replace(/(\d{3})(?=\d)/g,"$1"+I)+(M?t+Math.abs(A-e).toFixed(M).slice(2):"")},g.naturalDay=function(A,M){A=void 0===A?g.time():A,M=void 0===M?"Y-m-d":M;var t=86400,I=new Date,e=new Date(I.getFullYear(),I.getMonth(),I.getDate()).getTime()/1e3;return A=e-t?"yesterday":A>=e&&A=e+t&&A-2)return(t>=0?"just ":"")+"now";if(t<60&&t>-60)return t>=0?Math.floor(t)+" seconds ago":"in "+Math.floor(-t)+" seconds";if(t<120&&t>-120)return t>=0?"about a minute ago":"in about a minute";if(t<3600&&t>-3600)return t>=0?Math.floor(t/60)+" minutes ago":"in "+Math.floor(-t/60)+" minutes";if(t<7200&&t>-7200)return t>=0?"about an hour ago":"in about an hour";if(t<86400&&t>-86400)return t>=0?Math.floor(t/3600)+" hours ago":"in "+Math.floor(-t/3600)+" hours";var I=172800;if(t-I)return t>=0?"1 day ago":"in 1 day";var e=2505600;if(t-e)return t>=0?Math.floor(t/86400)+" days ago":"in "+Math.floor(-t/86400)+" days";var i=5184e3;if(t-i)return t>=0?"about a month ago":"in about a month";var T=parseInt(g.date("Y",M),10),E=parseInt(g.date("Y",A),10),N=12*T+parseInt(g.date("n",M),10),o=12*E+parseInt(g.date("n",A),10),n=N-o;if(n<12&&n>-12)return n>=0?n+" months ago":"in "+-n+" months";var C=T-E;return C<2&&C>-2?C>=0?"a year ago":"in a year":C>=0?C+" years ago":"in "+-C+" years"},g.ordinal=function(A){A=parseInt(A,10),A=isNaN(A)?0:A;var M=A<0?"-":"";A=Math.abs(A);var t=A%100;return M+A+(t>4&&t<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th")},g.filesize=function(A,M,t,I,e,i){return M=void 0===M?1024:M,A<=0?"0 bytes":(A

    "),A=A.replace(/\n/g,"
    "),"

    "+A+"

    "},g.nl2br=function(A){return A.replace(/(\r\n|\n|\r)/g,"
    ")},g.truncatechars=function(A,M){return A.length<=M?A:A.substr(0,M)+"…"},g.truncatewords=function(A,M){var t=A.split(" ");return t.length0,Q=C.enumErrorProps&&(A===u||A instanceof Error),r=C.enumPrototypes&&T(A);++IM.documentElement.clientHeight;return{modalStyles:{paddingRight:I&&!g?Q.default():void 0,paddingLeft:!I&&g?Q.default():void 0}}}});X.Body=z.default,X.Header=U.default,X.Title=m.default,X.Footer=f.default,X.Dialog=h.default,X.TRANSITION_DURATION=300,X.BACKDROP_TRANSITION_DURATION=150,M.default=c.bsSizes([a.Sizes.LARGE,a.Sizes.SMALL],c.bsClass("modal",X)),A.exports=M.default},function(A,M,t){"use strict";var I=t(15).default,g=t(14).default,e=t(38).default,i=t(7).default,T=t(6).default;M.__esModule=!0;var E=t(1),N=T(E),o=t(5),n=T(o),C=t(11),c=T(C),D=t(44),a=T(D),B=function(A){function M(){g(this,M),A.apply(this,arguments)}return I(M,A),M.prototype.render=function(){var A=this.props,M=A["aria-label"],t=e(A,["aria-label"]),I=a.default(this.context.$bs_onModalHide,this.props.onHide);return N.default.createElement("div",i({},t,{className:n.default(this.props.className,c.default.prefix(this.props,"header"))}),this.props.closeButton&&N.default.createElement("button",{type:"button",className:"close","aria-label":M,onClick:I},N.default.createElement("span",{"aria-hidden":"true"},"×")),this.props.children)},M}(N.default.Component);B.propTypes={"aria-label":N.default.PropTypes.string, -bsClass:N.default.PropTypes.string,closeButton:N.default.PropTypes.bool,onHide:N.default.PropTypes.func},B.contextTypes={$bs_onModalHide:N.default.PropTypes.func},B.defaultProps={"aria-label":"Close",closeButton:!1},M.default=C.bsClass("modal",B),A.exports=M.default},function(A,M,t){"use strict";function I(A,M){return Array.isArray(M)?M.indexOf(A)>=0:A===M}var g=t(7).default,e=t(78).default,i=t(6).default;M.__esModule=!0;var T=t(40),E=i(T),N=t(170),o=i(N),n=t(1),C=i(n),c=t(16),D=i(c),a=t(127),B=(i(a),t(370)),Q=i(B),r=t(44),s=i(r),x=C.default.createClass({displayName:"OverlayTrigger",propTypes:g({},Q.default.propTypes,{trigger:C.default.PropTypes.oneOfType([C.default.PropTypes.oneOf(["click","hover","focus"]),C.default.PropTypes.arrayOf(C.default.PropTypes.oneOf(["click","hover","focus"]))]),delay:C.default.PropTypes.number,delayShow:C.default.PropTypes.number,delayHide:C.default.PropTypes.number,defaultOverlayShown:C.default.PropTypes.bool,overlay:C.default.PropTypes.node.isRequired,onBlur:C.default.PropTypes.func,onClick:C.default.PropTypes.func,onFocus:C.default.PropTypes.func,onMouseEnter:C.default.PropTypes.func,onMouseLeave:C.default.PropTypes.func,target:function(){},onHide:function(){},show:function(){}}),getDefaultProps:function(){return{defaultOverlayShown:!1,trigger:["hover","focus"]}},getInitialState:function(){return{isOverlayShown:this.props.defaultOverlayShown}},show:function(){this.setState({isOverlayShown:!0})},hide:function(){this.setState({isOverlayShown:!1})},toggle:function(){this.state.isOverlayShown?this.hide():this.show()},componentWillMount:function(){this.handleMouseOver=this.handleMouseOverOut.bind(null,this.handleDelayedShow),this.handleMouseOut=this.handleMouseOverOut.bind(null,this.handleDelayedHide)},componentDidMount:function(){this._mountNode=document.createElement("div"),this.renderOverlay()},renderOverlay:function(){D.default.unstable_renderSubtreeIntoContainer(this,this._overlay,this._mountNode)},componentWillUnmount:function(){D.default.unmountComponentAtNode(this._mountNode),this._mountNode=null,clearTimeout(this._hoverShowDelay),clearTimeout(this._hoverHideDelay)},componentDidUpdate:function(){this._mountNode&&this.renderOverlay()},getOverlayTarget:function(){return D.default.findDOMNode(this)},getOverlay:function(){var A=g({},o.default(this.props,e(Q.default.propTypes)),{show:this.state.isOverlayShown,onHide:this.hide,target:this.getOverlayTarget,onExit:this.props.onExit,onExiting:this.props.onExiting,onExited:this.props.onExited,onEnter:this.props.onEnter,onEntering:this.props.onEntering,onEntered:this.props.onEntered}),M=n.cloneElement(this.props.overlay,{placement:A.placement,container:A.container});return C.default.createElement(Q.default,A,M)},render:function(){var A=C.default.Children.only(this.props.children),M=A.props,t={"aria-describedby":this.props.overlay.props.id};return this._overlay=this.getOverlay(),t.onClick=s.default(M.onClick,this.props.onClick),I("click",this.props.trigger)&&(t.onClick=s.default(this.toggle,t.onClick)),I("hover",this.props.trigger)&&(t.onMouseOver=s.default(this.handleMouseOver,this.props.onMouseOver,M.onMouseOver),t.onMouseOut=s.default(this.handleMouseOut,this.props.onMouseOut,M.onMouseOut)),I("focus",this.props.trigger)&&(t.onFocus=s.default(this.handleDelayedShow,this.props.onFocus,M.onFocus),t.onBlur=s.default(this.handleDelayedHide,this.props.onBlur,M.onBlur)),n.cloneElement(A,t)},handleDelayedShow:function(){var A=this;if(null!=this._hoverHideDelay)return clearTimeout(this._hoverHideDelay),void(this._hoverHideDelay=null);if(!this.state.isOverlayShown&&null==this._hoverShowDelay){var M=null!=this.props.delayShow?this.props.delayShow:this.props.delay;return M?void(this._hoverShowDelay=setTimeout(function(){A._hoverShowDelay=null,A.show()},M)):void this.show()}},handleDelayedHide:function(){var A=this;if(null!=this._hoverShowDelay)return clearTimeout(this._hoverShowDelay),void(this._hoverShowDelay=null);if(this.state.isOverlayShown&&null==this._hoverHideDelay){var M=null!=this.props.delayHide?this.props.delayHide:this.props.delay;return M?void(this._hoverHideDelay=setTimeout(function(){A._hoverHideDelay=null,A.hide()},M)):void this.hide()}},handleMouseOverOut:function(A,M){var t=M.currentTarget,I=M.relatedTarget||M.nativeEvent.toElement;I&&(I===t||E.default(t,I))||A(M)}});M.default=x,A.exports=M.default},function(A,M,t){"use strict";var I=t(7).default,g=t(6).default;M.__esModule=!0;var e=t(1),i=g(e),T=t(5),E=g(T),N=t(11),o=g(N),n=t(183),C=g(n),c=i.default.createClass({displayName:"Tooltip",propTypes:{id:C.default(i.default.PropTypes.oneOfType([i.default.PropTypes.string,i.default.PropTypes.number])),placement:i.default.PropTypes.oneOf(["top","right","bottom","left"]),positionLeft:i.default.PropTypes.number,positionTop:i.default.PropTypes.number,arrowOffsetLeft:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),arrowOffsetTop:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),title:i.default.PropTypes.node},getDefaultProps:function(){return{bsClass:"tooltip",placement:"right"}},render:function(){var A,M=(A={},A[o.default.prefix(this.props)]=!0,A[this.props.placement]=!0,A),t=I({left:this.props.positionLeft,top:this.props.positionTop},this.props.style),g={left:this.props.arrowOffsetLeft,top:this.props.arrowOffsetTop};return i.default.createElement("div",I({role:"tooltip"},this.props,{className:E.default(this.props.className,M),style:t}),i.default.createElement("div",{className:o.default.prefix(this.props,"arrow"),style:g}),i.default.createElement("div",{className:o.default.prefix(this.props,"inner")},this.props.children))}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){return A="function"==typeof A?A():A,i.default.findDOMNode(A)||M}Object.defineProperty(M,"__esModule",{value:!0}),M.default=g;var e=t(16),i=I(e);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement. You can usually obtain a ReactComponent or DOMElement from a ReactElement by attaching a ref to it."):"object"===E&&"function"==typeof i.render||1===i.nodeType?null:new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement.")}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M,t){"use strict";function I(){function A(A,M,I){for(var g=0;g>",null!=t[I]?A(t,I,g):M?new Error("Required prop '"+I+"' was not specified in '"+g+"'."):void 0}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}M.__esModule=!0,M.errMsg=t,M.createChainableTypeChecker=I},function(A,M){"use strict";function t(A,M,t){function I(){return i=!0,T?void(N=[].concat(Array.prototype.slice.call(arguments))):void t.apply(this,arguments)}function g(){if(!i&&(E=!0,!T)){for(T=!0;!i&&e=A&&E&&(i=!0,t()))}}var e=0,i=!1,T=!1,E=!1,N=void 0;g()}function I(A,M,t){function I(A,M,I){i||(M?(i=!0,t(M)):(e[A]=I,i=++T===g,i&&t(null,e)))}var g=A.length,e=[];if(0===g)return t(null,e);var i=!1,T=0;A.forEach(function(A,t){M(A,t,function(A,M){I(t,A,M)})})}M.__esModule=!0,M.loopAsync=t,M.mapAsync=I},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0,M.router=M.routes=M.route=M.components=M.component=M.location=M.history=M.falsy=M.locationShape=M.routerShape=void 0;var e=t(1),i=t(66),T=(g(i),t(34)),E=I(T),N=t(9),o=(g(N),e.PropTypes.func),n=e.PropTypes.object,C=e.PropTypes.shape,c=e.PropTypes.string,D=M.routerShape=C({push:o.isRequired,replace:o.isRequired,go:o.isRequired,goBack:o.isRequired,goForward:o.isRequired,setRouteLeaveHook:o.isRequired,isActive:o.isRequired}),a=M.locationShape=C({pathname:c.isRequired,search:c.isRequired,state:n,action:c.isRequired,key:c}),B=M.falsy=E.falsy,Q=M.history=E.history,r=M.location=a,s=M.component=E.component,x=M.components=E.components,j=M.route=E.route,y=(M.routes=E.routes,M.router=D),u={falsy:B,history:Q,location:r,component:s,components:x,route:j,router:y};M.default=u},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!0;return!1}function e(A,M){function t(M){var t=!(arguments.length<=1||void 0===arguments[1])&&arguments[1],I=arguments.length<=2||void 0===arguments[2]?null:arguments[2],g=void 0;return t&&t!==!0||null!==I?(M={pathname:M,query:t},g=I||!1):(M=A.createLocation(M),g=t),(0,C.default)(M,g,s.location,s.routes,s.params)}function I(A,t){x&&x.location===A?e(x,t):(0,B.default)(M,A,function(M,I){M?t(M):I?e(i({},I,{location:A}),t):t()})}function e(A,M){function t(t,g){return t||g?I(t,g):void(0,D.default)(A,function(t,I){t?M(t):M(null,null,s=i({},A,{components:I}))})}function I(A,t){A?M(A):M(null,t)}var g=(0,N.default)(s,A),e=g.leaveRoutes,T=g.changeRoutes,E=g.enterRoutes;(0,o.runLeaveHooks)(e,s),e.filter(function(A){return E.indexOf(A)===-1}).forEach(a),(0,o.runChangeHooks)(T,s,A,function(M,g){return M||g?I(M,g):void(0,o.runEnterHooks)(E,A,t)})}function T(A){var M=arguments.length<=1||void 0===arguments[1]||arguments[1];return A.__id__||M&&(A.__id__=j++)}function E(A){return A.reduce(function(A,M){return A.push.apply(A,y[T(M)]),A},[])}function n(A,t){(0,B.default)(M,A,function(M,I){if(null==I)return void t();x=i({},I,{location:A});for(var g=E((0,N.default)(s,x).leaveRoutes),e=void 0,T=0,o=g.length;null==e&&T=32||13===M?M:0}A.exports=t},function(A,M){"use strict";function t(A){var M=this,t=M.nativeEvent;if(t.getModifierState)return t.getModifierState(A);var I=g[A];return!!I&&!!t[I]}function I(A){return t}var g={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};A.exports=I},function(A,M){"use strict";function t(A){var M=A.target||A.srcElement||window;return 3===M.nodeType?M.parentNode:M}A.exports=t},function(A,M){"use strict";function t(A){var M=A&&(I&&A[I]||A[g]);if("function"==typeof M)return M}var I="function"==typeof Symbol&&Symbol.iterator,g="@@iterator";A.exports=t},function(A,M,t){"use strict";function I(A){return"function"==typeof A&&"undefined"!=typeof A.prototype&&"function"==typeof A.prototype.mountComponent&&"function"==typeof A.prototype.receiveComponent}function g(A){var M;if(null===A||A===!1)M=new i(g);else if("object"==typeof A){var t=A;!t||"function"!=typeof t.type&&"string"!=typeof t.type?N(!1):void 0,M="string"==typeof t.type?T.createInternalComponent(t):I(t.type)?new t.type(t):new o}else"string"==typeof A||"number"==typeof A?M=T.createInstanceForText(A):N(!1);return M.construct(A),M._mountIndex=0,M._mountImage=null,M}var e=t(443),i=t(215),T=t(221),E=t(4),N=t(2),o=(t(3),function(){});E(o.prototype,e.Mixin,{_instantiateReactComponent:g}),A.exports=g},function(A,M,t){"use strict";/** +!function(){"use strict";function t(){for(var A=[],M=0;M2?t-2:0),g=2;g1){for(var c=Array(C),D=0;D1){for(var a=Array(D),B=0;B3&&void 0!==arguments[3]?arguments[3]:{},N=Boolean(A),C=A||w,D=void 0;D="function"==typeof M?M:M?(0,Q.default)(M):L;var B=t||l,r=I.pure,s=void 0===r||r,x=I.withRef,y=void 0!==x&&x,h=s&&B!==l,S=d++;return function(A){function M(A,M,t){var I=B(A,M,t);return I}var t="Connect("+T(A)+")",I=function(I){function T(A,M){g(this,T);var i=e(this,I.call(this,A,M));i.version=S,i.store=A.store||M.store,(0,u.default)(i.store,'Could not find "store" in either the context or '+('props of "'+t+'". ')+"Either wrap the root component in a , "+('or explicitly pass "store" as a prop to "'+t+'".'));var E=i.store.getState();return i.state={storeState:E},i.clearCache(),i}return i(T,I),T.prototype.shouldComponentUpdate=function(){return!s||this.haveOwnPropsChanged||this.hasStoreStateChanged},T.prototype.computeStateProps=function(A,M){if(!this.finalMapStateToProps)return this.configureFinalMapState(A,M);var t=A.getState(),I=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(t,M):this.finalMapStateToProps(t);return I},T.prototype.configureFinalMapState=function(A,M){var t=C(A.getState(),M),I="function"==typeof t;return this.finalMapStateToProps=I?t:C,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,I?this.computeStateProps(A,M):t},T.prototype.computeDispatchProps=function(A,M){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(A,M);var t=A.dispatch,I=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(t,M):this.finalMapDispatchToProps(t);return I},T.prototype.configureFinalMapDispatch=function(A,M){var t=D(A.dispatch,M),I="function"==typeof t;return this.finalMapDispatchToProps=I?t:D,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,I?this.computeDispatchProps(A,M):t},T.prototype.updateStatePropsIfNeeded=function(){var A=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,a.default)(A,this.stateProps))&&(this.stateProps=A,!0)},T.prototype.updateDispatchPropsIfNeeded=function(){var A=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,a.default)(A,this.dispatchProps))&&(this.dispatchProps=A,!0)},T.prototype.updateMergedPropsIfNeeded=function(){var A=M(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&h&&(0,a.default)(A,this.mergedProps))&&(this.mergedProps=A,!0)},T.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},T.prototype.trySubscribe=function(){N&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},T.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},T.prototype.componentDidMount=function(){this.trySubscribe()},T.prototype.componentWillReceiveProps=function(A){s&&(0,a.default)(A,this.props)||(this.haveOwnPropsChanged=!0)},T.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},T.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},T.prototype.handleChange=function(){if(this.unsubscribe){var A=this.store.getState(),M=this.state.storeState;if(!s||M!==A){if(s&&!this.doStatePropsDependOnOwnProps){var t=E(this.updateStatePropsIfNeeded,this);if(!t)return;t===Y&&(this.statePropsPrecalculationError=Y.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:A})}}},T.prototype.getWrappedInstance=function(){return(0,u.default)(y,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},T.prototype.render=function(){var M=this.haveOwnPropsChanged,t=this.hasStoreStateChanged,I=this.haveStatePropsBeenPrecalculated,g=this.statePropsPrecalculationError,e=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,g)throw g;var i=!0,T=!0;s&&e&&(i=t||M&&this.doStatePropsDependOnOwnProps,T=M&&this.doDispatchPropsDependOnOwnProps);var E=!1,N=!1;I?E=!0:i&&(E=this.updateStatePropsIfNeeded()),T&&(N=this.updateDispatchPropsIfNeeded());var C=!0;return C=!!(E||N||M)&&this.updateMergedPropsIfNeeded(),!C&&e?e:(y?this.renderedElement=(0,n.createElement)(A,o({},this.mergedProps,{ref:"wrappedInstance"})):this.renderedElement=(0,n.createElement)(A,this.mergedProps),this.renderedElement)},T}(n.Component);return I.displayName=t,I.WrappedComponent=A,I.contextTypes={store:c.default},I.propTypes={store:c.default},(0,j.default)(I,A)}}M.__esModule=!0;var o=Object.assign||function(A){for(var M=1;M should not have a "'+M+'" prop')}M.__esModule=!0,M.routes=M.route=M.components=M.component=M.history=void 0,M.falsy=I;var g=t(1),e=g.PropTypes.func,i=g.PropTypes.object,T=g.PropTypes.arrayOf,E=g.PropTypes.oneOfType,N=g.PropTypes.element,o=g.PropTypes.shape,n=g.PropTypes.string,C=(M.history=o({listen:e.isRequired,push:e.isRequired,replace:e.isRequired,go:e.isRequired,goBack:e.isRequired,goForward:e.isRequired}),M.component=E([e,n])),c=(M.components=E([C,i]),M.route=E([i,N]));M.routes=E([c,T(c)])},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){var M=A.match(/^https?:\/\/[^\/]*/);return null==M?A:A.substring(M[0].length)}function e(A){var M=g(A),t="",I="",e=M.indexOf("#");e!==-1&&(I=M.substring(e),M=M.substring(0,e));var i=M.indexOf("?");return i!==-1&&(t=M.substring(i),M=M.substring(0,i)),""===M&&(M="/"),{pathname:M,search:t,hash:I}}M.__esModule=!0,M.extractPath=g,M.parsePath=e;var i=t(23);I(i)},function(A,M,t){"use strict";function I(){g.attachRefs(this,this._currentElement)}var g=t(459),e={mountComponent:function(A,M,t,g){var e=A.mountComponent(M,t,g);return A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A),e},unmountComponent:function(A){g.detachRefs(A,A._currentElement),A.unmountComponent()},receiveComponent:function(A,M,t,e){var i=A._currentElement;if(M!==i||e!==A._context){var T=g.shouldUpdateRefs(i,M);T&&g.detachRefs(A,i),A.receiveComponent(M,t,e),T&&A._currentElement&&null!=A._currentElement.ref&&t.getReactMountReady().enqueue(I,A)}},performUpdateIfNecessary:function(A,M){A.performUpdateIfNecessary(M)}};A.exports=e},function(A,M,t){"use strict";function I(A,M,t,I){this.dispatchConfig=A,this.dispatchMarker=M,this.nativeEvent=t;var g=this.constructor.Interface;for(var e in g)if(g.hasOwnProperty(e)){var T=g[e];T?this[e]=T(t):"target"===e?this.target=I:this[e]=t[e]}var E=null!=t.defaultPrevented?t.defaultPrevented:t.returnValue===!1;E?this.isDefaultPrevented=i.thatReturnsTrue:this.isDefaultPrevented=i.thatReturnsFalse,this.isPropagationStopped=i.thatReturnsFalse}var g=t(31),e=t(4),i=t(20),T=(t(3),{type:null,target:null,currentTarget:i.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(A){return A.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null});e(I.prototype,{preventDefault:function(){this.defaultPrevented=!0;var A=this.nativeEvent;A&&(A.preventDefault?A.preventDefault():A.returnValue=!1,this.isDefaultPrevented=i.thatReturnsTrue)},stopPropagation:function(){var A=this.nativeEvent;A&&(A.stopPropagation?A.stopPropagation():A.cancelBubble=!0,this.isPropagationStopped=i.thatReturnsTrue)},persist:function(){this.isPersistent=i.thatReturnsTrue},isPersistent:i.thatReturnsFalse,destructor:function(){var A=this.constructor.Interface;for(var M in A)this[M]=null;this.dispatchConfig=null,this.dispatchMarker=null,this.nativeEvent=null}}),I.Interface=T,I.augmentClass=function(A,M){var t=this,I=Object.create(t.prototype);e(I,A.prototype),A.prototype=I,A.prototype.constructor=A,A.Interface=e({},t.Interface,M),A.augmentClass=t.augmentClass,g.addPoolingTo(A,g.fourArgumentPooler)},g.addPoolingTo(I,g.fourArgumentPooler),A.exports=I},function(A,M){"use strict";M.default=function(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t},M.__esModule=!0},function(A,M){"use strict";function t(A){return A&&A.ownerDocument||document}M.__esModule=!0,M.default=t,A.exports=M.default},function(A,M,t){"use strict";var I=t(32),g=function(){var A=I&&document.documentElement;return A&&A.contains?function(A,M){return A.contains(M)}:A&&A.compareDocumentPosition?function(A,M){return A===M||!!(16&A.compareDocumentPosition(M))}:function(A,M){if(M)do if(M===A)return!0;while(M=M.parentNode);return!1}}();A.exports=g},function(A,M){function t(A){return"number"==typeof A&&A>-1&&A%1==0&&A<=I}var I=9007199254740991;A.exports=t},function(A,M,t){(function(A){!function(M,t){A.exports=t()}(this,function(){"use strict";function M(){return aI.apply(null,arguments)}function t(A){aI=A}function I(A){return A instanceof Array||"[object Array]"===Object.prototype.toString.call(A)}function g(A){return null!=A&&"[object Object]"===Object.prototype.toString.call(A)}function e(A){var M;for(M in A)return!1;return!0}function i(A){return"number"==typeof A||"[object Number]"===Object.prototype.toString.call(A)}function T(A){return A instanceof Date||"[object Date]"===Object.prototype.toString.call(A)}function E(A,M){var t,I=[];for(t=0;t0)for(t in rI)I=rI[t],g=M[I],B(g)||(A[I]=g);return A}function r(A){Q(this,A),this._d=new Date(null!=A._d?A._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),sI===!1&&(sI=!0,M.updateOffset(this),sI=!1)}function s(A){return A instanceof r||null!=A&&null!=A._isAMomentObject}function x(A){return A<0?Math.ceil(A)||0:Math.floor(A)}function j(A){var M=+A,t=0;return 0!==M&&isFinite(M)&&(t=x(M)),t}function y(A,M,t){var I,g=Math.min(A.length,M.length),e=Math.abs(A.length-M.length),i=0;for(I=0;I0?"future":"past"];return l(t)?t(M):t.replace(/%s/i,M)}function F(A,M){var t=A.toLowerCase();SI[t]=SI[t+"s"]=SI[M]=A}function f(A){return"string"==typeof A?SI[A]||SI[A.toLowerCase()]:void 0}function k(A){var M,t,I={};for(t in A)N(A,t)&&(M=f(t),M&&(I[M]=A[t]));return I}function R(A,M){zI[A]=M}function J(A){var M=[];for(var t in A)M.push({unit:t,priority:zI[t]});return M.sort(function(A,M){return A.priority-M.priority}),M}function G(A,t){return function(I){return null!=I?(b(this,A,I),M.updateOffset(this,t),this):H(this,A)}}function H(A,M){return A.isValid()?A._d["get"+(A._isUTC?"UTC":"")+M]():NaN}function b(A,M,t){A.isValid()&&A._d["set"+(A._isUTC?"UTC":"")+M](t)}function X(A){return A=f(A),l(this[A])?this[A]():this}function v(A,M){if("object"==typeof A){A=k(A);for(var t=J(A),I=0;I=0;return(e?t?"+":"":"-")+Math.pow(10,Math.max(0,g)).toString().substr(1)+I}function V(A,M,t,I){var g=I;"string"==typeof I&&(g=function(){return this[I]()}),A&&(mI[A]=g),M&&(mI[M[0]]=function(){return W(g.apply(this,arguments),M[1],M[2])}),t&&(mI[t]=function(){return this.localeData().ordinal(g.apply(this,arguments),A)})}function P(A){return A.match(/\[[\s\S]/)?A.replace(/^\[|\]$/g,""):A.replace(/\\/g,"")}function Z(A){var M,t,I=A.match(pI);for(M=0,t=I.length;M=0&&UI.test(A);)A=A.replace(UI,t),UI.lastIndex=0,I-=1;return A}function _(A,M,t){$I[A]=l(M)?M:function(A,I){return A&&t?t:M}}function $(A,M){return N($I,A)?$I[A](M._strict,M._locale):new RegExp(AA(A))}function AA(A){return MA(A.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(A,M,t,I,g){return M||t||I||g}))}function MA(A){return A.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function tA(A,M){var t,I=M;for("string"==typeof A&&(A=[A]),i(M)&&(I=function(A,t){t[M]=j(A)}),t=0;t=0&&isFinite(T.getFullYear())&&T.setFullYear(A),T}function xA(A){var M=new Date(Date.UTC.apply(null,arguments));return A<100&&A>=0&&isFinite(M.getUTCFullYear())&&M.setUTCFullYear(A),M}function jA(A,M,t){var I=7+M-t,g=(7+xA(A,0,I).getUTCDay()-M)%7;return-g+I-1}function yA(A,M,t,I,g){var e,i,T=(7+t-I)%7,E=jA(A,I,g),N=1+7*(M-1)+T+E;return N<=0?(e=A-1,i=BA(e)+N):N>BA(A)?(e=A+1,i=N-BA(A)):(e=A,i=N),{year:e,dayOfYear:i}}function uA(A,M,t){var I,g,e=jA(A.year(),M,t),i=Math.floor((A.dayOfYear()-e-1)/7)+1;return i<1?(g=A.year()-1,I=i+wA(g,M,t)):i>wA(A.year(),M,t)?(I=i-wA(A.year(),M,t),g=A.year()+1):(g=A.year(),I=i),{week:I,year:g}}function wA(A,M,t){var I=jA(A,M,t),g=jA(A+1,M,t);return(BA(A)-I+g)/7}function LA(A){return uA(A,this._week.dow,this._week.doy).week}function lA(){return this._week.dow}function YA(){return this._week.doy}function dA(A){var M=this.localeData().week(this);return null==A?M:this.add(7*(A-M),"d")}function hA(A){var M=uA(this,1,4).week;return null==A?M:this.add(7*(A-M),"d")}function SA(A,M){return"string"!=typeof A?A:isNaN(A)?(A=M.weekdaysParse(A),"number"==typeof A?A:null):parseInt(A,10)}function zA(A,M){return"string"==typeof A?M.weekdaysParse(A)%7||7:isNaN(A)?null:A}function pA(A,M){return A?I(this._weekdays)?this._weekdays[A.day()]:this._weekdays[this._weekdays.isFormat.test(M)?"format":"standalone"][A.day()]:this._weekdays}function UA(A){return A?this._weekdaysShort[A.day()]:this._weekdaysShort}function OA(A){return A?this._weekdaysMin[A.day()]:this._weekdaysMin}function mA(A,M,t){var I,g,e,i=A.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],I=0;I<7;++I)e=n([2e3,1]).day(I),this._minWeekdaysParse[I]=this.weekdaysMin(e,"").toLocaleLowerCase(),this._shortWeekdaysParse[I]=this.weekdaysShort(e,"").toLocaleLowerCase(),this._weekdaysParse[I]=this.weekdays(e,"").toLocaleLowerCase();return t?"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:null):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null):"dddd"===M?(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):"ddd"===M?(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._minWeekdaysParse,i),g!==-1?g:null))):(g=og.call(this._minWeekdaysParse,i),g!==-1?g:(g=og.call(this._weekdaysParse,i),g!==-1?g:(g=og.call(this._shortWeekdaysParse,i),g!==-1?g:null)))}function FA(A,M,t){var I,g,e;if(this._weekdaysParseExact)return mA.call(this,A,M,t);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),I=0;I<7;I++){if(g=n([2e3,1]).day(I),t&&!this._fullWeekdaysParse[I]&&(this._fullWeekdaysParse[I]=new RegExp("^"+this.weekdays(g,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[I]=new RegExp("^"+this.weekdaysShort(g,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[I]=new RegExp("^"+this.weekdaysMin(g,"").replace(".",".?")+"$","i")),this._weekdaysParse[I]||(e="^"+this.weekdays(g,"")+"|^"+this.weekdaysShort(g,"")+"|^"+this.weekdaysMin(g,""),this._weekdaysParse[I]=new RegExp(e.replace(".",""),"i")),t&&"dddd"===M&&this._fullWeekdaysParse[I].test(A))return I;if(t&&"ddd"===M&&this._shortWeekdaysParse[I].test(A))return I;if(t&&"dd"===M&&this._minWeekdaysParse[I].test(A))return I;if(!t&&this._weekdaysParse[I].test(A))return I}}function fA(A){if(!this.isValid())return null!=A?this:NaN;var M=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=A?(A=SA(A,this.localeData()),this.add(A-M,"d")):M}function kA(A){if(!this.isValid())return null!=A?this:NaN;var M=(this.day()+7-this.localeData()._week.dow)%7;return null==A?M:this.add(A-M,"d")}function RA(A){if(!this.isValid())return null!=A?this:NaN;if(null!=A){var M=zA(A,this.localeData());return this.day(this.day()%7?M:M-7)}return this.day()||7}function JA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysStrictRegex:this._weekdaysRegex):(N(this,"_weekdaysRegex")||(this._weekdaysRegex=jg),this._weekdaysStrictRegex&&A?this._weekdaysStrictRegex:this._weekdaysRegex)}function GA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(N(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=yg),this._weekdaysShortStrictRegex&&A?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function HA(A){return this._weekdaysParseExact?(N(this,"_weekdaysRegex")||bA.call(this),A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(N(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=ug),this._weekdaysMinStrictRegex&&A?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function bA(){function A(A,M){return M.length-A.length}var M,t,I,g,e,i=[],T=[],E=[],N=[];for(M=0;M<7;M++)t=n([2e3,1]).day(M),I=this.weekdaysMin(t,""),g=this.weekdaysShort(t,""),e=this.weekdays(t,""),i.push(I),T.push(g),E.push(e),N.push(I),N.push(g),N.push(e);for(i.sort(A),T.sort(A),E.sort(A),N.sort(A),M=0;M<7;M++)T[M]=MA(T[M]),E[M]=MA(E[M]),N[M]=MA(N[M]);this._weekdaysRegex=new RegExp("^("+N.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+E.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+T.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function XA(){return this.hours()%12||12}function vA(){return this.hours()||24}function WA(A,M){V(A,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),M)})}function VA(A,M){return M._meridiemParse}function PA(A){return"p"===(A+"").toLowerCase().charAt(0)}function ZA(A,M,t){return A>11?t?"pm":"PM":t?"am":"AM"}function KA(A){return A?A.toLowerCase().replace("_","-"):A}function qA(A){for(var M,t,I,g,e=0;e0;){if(I=_A(g.slice(0,M).join("-")))return I;if(t&&t.length>=M&&y(g,t,!0)>=M-1)break;M--}e++}return null}function _A(M){var t=null;if(!dg[M]&&"undefined"!=typeof A&&A&&A.exports)try{t=wg._abbr,!function(){var A=new Error('Cannot find module "./locale"');throw A.code="MODULE_NOT_FOUND",A}(),$A(t)}catch(A){}return dg[M]}function $A(A,M){var t;return A&&(t=B(M)?tM(A):AM(A,M),t&&(wg=t)),wg._abbr}function AM(A,M){if(null!==M){var t=Yg;if(M.abbr=A,null!=dg[A])L("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),t=dg[A]._config;else if(null!=M.parentLocale){if(null==dg[M.parentLocale])return hg[M.parentLocale]||(hg[M.parentLocale]=[]),hg[M.parentLocale].push({name:A,config:M}),null;t=dg[M.parentLocale]._config}return dg[A]=new h(d(t,M)),hg[A]&&hg[A].forEach(function(A){AM(A.name,A.config)}),$A(A),dg[A]}return delete dg[A],null}function MM(A,M){if(null!=M){var t,I=Yg;null!=dg[A]&&(I=dg[A]._config),M=d(I,M),t=new h(M),t.parentLocale=dg[A],dg[A]=t,$A(A)}else null!=dg[A]&&(null!=dg[A].parentLocale?dg[A]=dg[A].parentLocale:null!=dg[A]&&delete dg[A]);return dg[A]}function tM(A){var M;if(A&&A._locale&&A._locale._abbr&&(A=A._locale._abbr),!A)return wg;if(!I(A)){if(M=_A(A))return M;A=[A]}return qA(A)}function IM(){return uI(dg)}function gM(A){var M,t=A._a;return t&&c(A).overflow===-2&&(M=t[tg]<0||t[tg]>11?tg:t[Ig]<1||t[Ig]>eA(t[Mg],t[tg])?Ig:t[gg]<0||t[gg]>24||24===t[gg]&&(0!==t[eg]||0!==t[ig]||0!==t[Tg])?gg:t[eg]<0||t[eg]>59?eg:t[ig]<0||t[ig]>59?ig:t[Tg]<0||t[Tg]>999?Tg:-1,c(A)._overflowDayOfYear&&(MIg)&&(M=Ig),c(A)._overflowWeeks&&M===-1&&(M=Eg),c(A)._overflowWeekday&&M===-1&&(M=Ng),c(A).overflow=M),A}function eM(A){var M,t,I,g,e,i,T=A._i,E=Sg.exec(T)||zg.exec(T);if(E){for(c(A).iso=!0,M=0,t=Ug.length;MBA(g)&&(c(A)._overflowDayOfYear=!0),t=xA(g,0,A._dayOfYear),A._a[tg]=t.getUTCMonth(),A._a[Ig]=t.getUTCDate()),M=0;M<3&&null==A._a[M];++M)A._a[M]=e[M]=I[M];for(;M<7;M++)A._a[M]=e[M]=null==A._a[M]?2===M?1:0:A._a[M];24===A._a[gg]&&0===A._a[eg]&&0===A._a[ig]&&0===A._a[Tg]&&(A._nextDay=!0,A._a[gg]=0),A._d=(A._useUTC?xA:sA).apply(null,e),null!=A._tzm&&A._d.setUTCMinutes(A._d.getUTCMinutes()-A._tzm),A._nextDay&&(A._a[gg]=24)}}function oM(A){var M,t,I,g,e,i,T,E;if(M=A._w,null!=M.GG||null!=M.W||null!=M.E)e=1,i=4,t=TM(M.GG,A._a[Mg],uA(sM(),1,4).year),I=TM(M.W,1),g=TM(M.E,1),(g<1||g>7)&&(E=!0);else{e=A._locale._week.dow,i=A._locale._week.doy;var N=uA(sM(),e,i);t=TM(M.gg,A._a[Mg],N.year),I=TM(M.w,N.week),null!=M.d?(g=M.d,(g<0||g>6)&&(E=!0)):null!=M.e?(g=M.e+e,(M.e<0||M.e>6)&&(E=!0)):g=e}I<1||I>wA(t,e,i)?c(A)._overflowWeeks=!0:null!=E?c(A)._overflowWeekday=!0:(T=yA(t,I,g,e,i),A._a[Mg]=T.year,A._dayOfYear=T.dayOfYear)}function nM(A){if(A._f===M.ISO_8601)return void eM(A);A._a=[],c(A).empty=!0;var t,I,g,e,i,T=""+A._i,E=T.length,N=0;for(g=q(A._f,A._locale).match(pI)||[],t=0;t0&&c(A).unusedInput.push(i),T=T.slice(T.indexOf(I)+I.length),N+=I.length),mI[e]?(I?c(A).empty=!1:c(A).unusedTokens.push(e),gA(e,I,A)):A._strict&&!I&&c(A).unusedTokens.push(e);c(A).charsLeftOver=E-N,T.length>0&&c(A).unusedInput.push(T),A._a[gg]<=12&&c(A).bigHour===!0&&A._a[gg]>0&&(c(A).bigHour=void 0),c(A).parsedDateParts=A._a.slice(0),c(A).meridiem=A._meridiem,A._a[gg]=CM(A._locale,A._a[gg],A._meridiem),NM(A),gM(A)}function CM(A,M,t){var I;return null==t?M:null!=A.meridiemHour?A.meridiemHour(M,t):null!=A.isPM?(I=A.isPM(t),I&&M<12&&(M+=12),I||12!==M||(M=0),M):M}function cM(A){var M,t,I,g,e;if(0===A._f.length)return c(A).invalidFormat=!0,void(A._d=new Date(NaN));for(g=0;gthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function fM(){if(!B(this._isDSTShifted))return this._isDSTShifted;var A={};if(Q(A,this),A=BM(A),A._a){var M=A._isUTC?n(A._a):sM(A._a);this._isDSTShifted=this.isValid()&&y(A._a,M.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function kM(){return!!this.isValid()&&!this._isUTC}function RM(){return!!this.isValid()&&this._isUTC}function JM(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function GM(A,M){var t,I,g,e=A,T=null;return wM(A)?e={ms:A._milliseconds,d:A._days,M:A._months}:i(A)?(e={},M?e[M]=A:e.milliseconds=A):(T=Jg.exec(A))?(t="-"===T[1]?-1:1,e={y:0,d:j(T[Ig])*t,h:j(T[gg])*t,m:j(T[eg])*t,s:j(T[ig])*t,ms:j(LM(1e3*T[Tg]))*t}):(T=Gg.exec(A))?(t="-"===T[1]?-1:1,e={y:HM(T[2],t),M:HM(T[3],t),w:HM(T[4],t),d:HM(T[5],t),h:HM(T[6],t),m:HM(T[7],t),s:HM(T[8],t)}):null==e?e={}:"object"==typeof e&&("from"in e||"to"in e)&&(g=XM(sM(e.from),sM(e.to)),e={},e.ms=g.milliseconds,e.M=g.months),I=new uM(e),wM(A)&&N(A,"_locale")&&(I._locale=A._locale),I}function HM(A,M){var t=A&&parseFloat(A.replace(",","."));return(isNaN(t)?0:t)*M}function bM(A,M){var t={milliseconds:0,months:0};return t.months=M.month()-A.month()+12*(M.year()-A.year()),A.clone().add(t.months,"M").isAfter(M)&&--t.months,t.milliseconds=+M-+A.clone().add(t.months,"M"),t}function XM(A,M){var t;return A.isValid()&&M.isValid()?(M=dM(M,A),A.isBefore(M)?t=bM(A,M):(t=bM(M,A),t.milliseconds=-t.milliseconds,t.months=-t.months),t):{milliseconds:0,months:0}}function vM(A,M){return function(t,I){var g,e;return null===I||isNaN(+I)||(L(M,"moment()."+M+"(period, number) is deprecated. Please use moment()."+M+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),e=t,t=I,I=e),t="string"==typeof t?+t:t,g=GM(t,I),WM(this,g,A),this}}function WM(A,t,I,g){var e=t._milliseconds,i=LM(t._days),T=LM(t._months);A.isValid()&&(g=null==g||g,e&&A._d.setTime(A._d.valueOf()+e*I),i&&b(A,"Date",H(A,"Date")+i*I),T&&oA(A,H(A,"Month")+T*I),g&&M.updateOffset(A,i||T))}function VM(A,M){var t=A.diff(M,"days",!0);return t<-6?"sameElse":t<-1?"lastWeek":t<0?"lastDay":t<1?"sameDay":t<2?"nextDay":t<7?"nextWeek":"sameElse"}function PM(A,t){var I=A||sM(),g=dM(I,this).startOf("day"),e=M.calendarFormat(this,g)||"sameElse",i=t&&(l(t[e])?t[e].call(this,I):t[e]);return this.format(i||this.localeData().calendar(e,this,sM(I)))}function ZM(){return new r(this)}function KM(A,M){var t=s(A)?A:sM(A);return!(!this.isValid()||!t.isValid())&&(M=f(B(M)?"millisecond":M),"millisecond"===M?this.valueOf()>t.valueOf():t.valueOf()e&&(M=e),pt.call(this,A,M,t,I,g))}function pt(A,M,t,I,g){var e=yA(A,M,t,I,g),i=xA(e.year,0,e.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}function Ut(A){return null==A?Math.ceil((this.month()+1)/3):this.month(3*(A-1)+this.month()%3)}function Ot(A){var M=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==A?M:this.add(A-M,"d")}function mt(A,M){M[Tg]=j(1e3*("0."+A))}function Ft(){return this._isUTC?"UTC":""}function ft(){return this._isUTC?"Coordinated Universal Time":""}function kt(A){return sM(1e3*A)}function Rt(){return sM.apply(null,arguments).parseZone()}function Jt(A){return A}function Gt(A,M,t,I){var g=tM(),e=n().set(I,M);return g[t](e,A)}function Ht(A,M,t){if(i(A)&&(M=A,A=void 0),A=A||"",null!=M)return Gt(A,M,t,"month");var I,g=[];for(I=0;I<12;I++)g[I]=Gt(A,I,t,"month");return g}function bt(A,M,t,I){"boolean"==typeof A?(i(M)&&(t=M,M=void 0),M=M||""):(M=A,t=M,A=!1,i(M)&&(t=M,M=void 0),M=M||"");var g=tM(),e=A?g._week.dow:0;if(null!=t)return Gt(M,(t+e)%7,I,"day");var T,E=[];for(T=0;T<7;T++)E[T]=Gt(M,(T+e)%7,I,"day");return E}function Xt(A,M){return Ht(A,M,"months")}function vt(A,M){return Ht(A,M,"monthsShort")}function Wt(A,M,t){return bt(A,M,t,"weekdays")}function Vt(A,M,t){return bt(A,M,t,"weekdaysShort")}function Pt(A,M,t){return bt(A,M,t,"weekdaysMin")}function Zt(){var A=this._data;return this._milliseconds=_g(this._milliseconds),this._days=_g(this._days),this._months=_g(this._months),A.milliseconds=_g(A.milliseconds),A.seconds=_g(A.seconds),A.minutes=_g(A.minutes),A.hours=_g(A.hours),A.months=_g(A.months),A.years=_g(A.years),this}function Kt(A,M,t,I){var g=GM(M,t);return A._milliseconds+=I*g._milliseconds,A._days+=I*g._days,A._months+=I*g._months,A._bubble()}function qt(A,M){return Kt(this,A,M,1)}function _t(A,M){return Kt(this,A,M,-1)}function $t(A){return A<0?Math.floor(A):Math.ceil(A)}function AI(){var A,M,t,I,g,e=this._milliseconds,i=this._days,T=this._months,E=this._data;return e>=0&&i>=0&&T>=0||e<=0&&i<=0&&T<=0||(e+=864e5*$t(tI(T)+i),i=0,T=0),E.milliseconds=e%1e3,A=x(e/1e3),E.seconds=A%60,M=x(A/60),E.minutes=M%60,t=x(M/60),E.hours=t%24,i+=x(t/24),g=x(MI(i)),T+=g,i-=$t(tI(g)),I=x(T/12),T%=12,E.days=i,E.months=T,E.years=I,this}function MI(A){return 4800*A/146097}function tI(A){return 146097*A/4800}function II(A){var M,t,I=this._milliseconds;if(A=f(A),"month"===A||"year"===A)return M=this._days+I/864e5,t=this._months+MI(M),"month"===A?t:t/12;switch(M=this._days+Math.round(tI(this._months)),A){case"week":return M/7+I/6048e5;case"day":return M+I/864e5;case"hour":return 24*M+I/36e5;case"minute":return 1440*M+I/6e4;case"second":return 86400*M+I/1e3;case"millisecond":return Math.floor(864e5*M)+I;default:throw new Error("Unknown unit "+A)}}function gI(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*j(this._months/12)}function eI(A){return function(){return this.as(A)}}function iI(A){return A=f(A),this[A+"s"]()}function TI(A){return function(){return this._data[A]}}function EI(){return x(this.days()/7)}function NI(A,M,t,I,g){return g.relativeTime(M||1,!!t,A,I)}function oI(A,M,t){var I=GM(A).abs(),g=De(I.as("s")),e=De(I.as("m")),i=De(I.as("h")),T=De(I.as("d")),E=De(I.as("M")),N=De(I.as("y")),o=g0,o[4]=t,NI.apply(null,o)}function nI(A){return void 0===A?De:"function"==typeof A&&(De=A,!0)}function CI(A,M){return void 0!==ae[A]&&(void 0===M?ae[A]:(ae[A]=M,!0))}function cI(A){var M=this.localeData(),t=oI(this,!A,M);return A&&(t=M.pastFuture(+this,t)),M.postformat(t)}function DI(){var A,M,t,I=Be(this._milliseconds)/1e3,g=Be(this._days),e=Be(this._months);A=x(I/60),M=x(A/60),I%=60,A%=60,t=x(e/12),e%=12;var i=t,T=e,E=g,N=M,o=A,n=I,C=this.asSeconds();return C?(C<0?"-":"")+"P"+(i?i+"Y":"")+(T?T+"M":"")+(E?E+"D":"")+(N||o||n?"T":"")+(N?N+"H":"")+(o?o+"M":"")+(n?n+"S":""):"P0D"}var aI,BI;BI=Array.prototype.some?Array.prototype.some:function(A){for(var M=Object(this),t=M.length>>>0,I=0;I68?1900:2e3)};var Bg=G("FullYear",!0);V("w",["ww",2],"wo","week"),V("W",["WW",2],"Wo","isoWeek"),F("week","w"),F("isoWeek","W"),R("week",5),R("isoWeek",5),_("w",GI),_("ww",GI,fI),_("W",GI),_("WW",GI,fI),IA(["w","ww","W","WW"],function(A,M,t,I){M[I.substr(0,1)]=j(A)});var Qg={dow:0,doy:6};V("d",0,"do","day"),V("dd",0,0,function(A){return this.localeData().weekdaysMin(this,A)}),V("ddd",0,0,function(A){return this.localeData().weekdaysShort(this,A)}),V("dddd",0,0,function(A){return this.localeData().weekdays(this,A)}),V("e",0,0,"weekday"),V("E",0,0,"isoWeekday"),F("day","d"),F("weekday","e"),F("isoWeekday","E"),R("day",11),R("weekday",11),R("isoWeekday",11),_("d",GI),_("e",GI),_("E",GI),_("dd",function(A,M){return M.weekdaysMinRegex(A)}),_("ddd",function(A,M){return M.weekdaysShortRegex(A)}),_("dddd",function(A,M){return M.weekdaysRegex(A)}),IA(["dd","ddd","dddd"],function(A,M,t,I){var g=t._locale.weekdaysParse(A,I,t._strict);null!=g?M.d=g:c(t).invalidWeekday=A}),IA(["d","e","E"],function(A,M,t,I){M[I]=j(A)});var rg="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),sg="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),xg="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),jg=_I,yg=_I,ug=_I;V("H",["HH",2],0,"hour"),V("h",["hh",2],0,XA),V("k",["kk",2],0,vA),V("hmm",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)}),V("hmmss",0,0,function(){return""+XA.apply(this)+W(this.minutes(),2)+W(this.seconds(),2)}),V("Hmm",0,0,function(){return""+this.hours()+W(this.minutes(),2)}),V("Hmmss",0,0,function(){return""+this.hours()+W(this.minutes(),2)+W(this.seconds(),2)}),WA("a",!0),WA("A",!1),F("hour","h"),R("hour",13),_("a",VA),_("A",VA),_("H",GI),_("h",GI),_("HH",GI,fI),_("hh",GI,fI),_("hmm",HI),_("hmmss",bI),_("Hmm",HI),_("Hmmss",bI),tA(["H","HH"],gg),tA(["a","A"],function(A,M,t){t._isPm=t._locale.isPM(A),t._meridiem=A}),tA(["h","hh"],function(A,M,t){M[gg]=j(A),c(t).bigHour=!0}),tA("hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I)),c(t).bigHour=!0}),tA("hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g)),c(t).bigHour=!0}),tA("Hmm",function(A,M,t){var I=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I))}),tA("Hmmss",function(A,M,t){var I=A.length-4,g=A.length-2;M[gg]=j(A.substr(0,I)),M[eg]=j(A.substr(I,2)),M[ig]=j(A.substr(g))});var wg,Lg=/[ap]\.?m?\.?/i,lg=G("Hours",!0),Yg={calendar:wI,longDateFormat:LI,invalidDate:lI,ordinal:YI,ordinalParse:dI,relativeTime:hI,months:Cg,monthsShort:cg,week:Qg,weekdays:rg,weekdaysMin:xg,weekdaysShort:sg,meridiemParse:Lg},dg={},hg={},Sg=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,zg=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,pg=/Z|[+-]\d\d(?::?\d\d)?/,Ug=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Og=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],mg=/^\/?Date\((\-?\d+)/i;M.createFromInputFallback=w("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(A){A._d=new Date(A._i+(A._useUTC?" UTC":""))}),M.ISO_8601=function(){};var Fg=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var A=sM.apply(null,arguments);return this.isValid()&&A.isValid()?Athis?this:A:a()}),kg=function(){return Date.now?Date.now():+new Date};lM("Z",":"),lM("ZZ",""),_("Z",KI),_("ZZ",KI),tA(["Z","ZZ"],function(A,M,t){t._useUTC=!0,t._tzm=YM(KI,A)});var Rg=/([\+\-]|\d\d)/gi;M.updateOffset=function(){};var Jg=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Gg=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;GM.fn=uM.prototype;var Hg=vM(1,"add"),bg=vM(-1,"subtract");M.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",M.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xg=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(A){return void 0===A?this.localeData():this.locale(A)});V(0,["gg",2],0,function(){return this.weekYear()%100}),V(0,["GG",2],0,function(){return this.isoWeekYear()%100}),lt("gggg","weekYear"),lt("ggggg","weekYear"),lt("GGGG","isoWeekYear"),lt("GGGGG","isoWeekYear"),F("weekYear","gg"),F("isoWeekYear","GG"),R("weekYear",1),R("isoWeekYear",1),_("G",PI),_("g",PI),_("GG",GI,fI),_("gg",GI,fI),_("GGGG",vI,RI),_("gggg",vI,RI),_("GGGGG",WI,JI),_("ggggg",WI,JI),IA(["gggg","ggggg","GGGG","GGGGG"],function(A,M,t,I){M[I.substr(0,2)]=j(A)}),IA(["gg","GG"],function(A,t,I,g){t[g]=M.parseTwoDigitYear(A)}),V("Q",0,"Qo","quarter"),F("quarter","Q"),R("quarter",7),_("Q",FI),tA("Q",function(A,M){M[tg]=3*(j(A)-1)}),V("D",["DD",2],"Do","date"),F("date","D"),R("date",9),_("D",GI),_("DD",GI,fI),_("Do",function(A,M){return A?M._ordinalParse:M._ordinalParseLenient}),tA(["D","DD"],Ig),tA("Do",function(A,M){M[Ig]=j(A.match(GI)[0],10)});var vg=G("Date",!0);V("DDD",["DDDD",3],"DDDo","dayOfYear"),F("dayOfYear","DDD"),R("dayOfYear",4),_("DDD",XI),_("DDDD",kI),tA(["DDD","DDDD"],function(A,M,t){t._dayOfYear=j(A)}),V("m",["mm",2],0,"minute"),F("minute","m"),R("minute",14),_("m",GI),_("mm",GI,fI),tA(["m","mm"],eg);var Wg=G("Minutes",!1);V("s",["ss",2],0,"second"),F("second","s"),R("second",15),_("s",GI),_("ss",GI,fI),tA(["s","ss"],ig);var Vg=G("Seconds",!1);V("S",0,0,function(){return~~(this.millisecond()/100)}),V(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),V(0,["SSS",3],0,"millisecond"),V(0,["SSSS",4],0,function(){return 10*this.millisecond()}),V(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),V(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),V(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),V(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),V(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),F("millisecond","ms"),R("millisecond",16),_("S",XI,FI),_("SS",XI,fI),_("SSS",XI,kI);var Pg;for(Pg="SSSS";Pg.length<=9;Pg+="S")_(Pg,VI);for(Pg="S";Pg.length<=9;Pg+="S")tA(Pg,mt);var Zg=G("Milliseconds",!1);V("z",0,0,"zoneAbbr"),V("zz",0,0,"zoneName");var Kg=r.prototype;Kg.add=Hg,Kg.calendar=PM,Kg.clone=ZM,Kg.diff=tt,Kg.endOf=at,Kg.format=Tt,Kg.from=Et,Kg.fromNow=Nt,Kg.to=ot,Kg.toNow=nt,Kg.get=X,Kg.invalidAt=wt,Kg.isAfter=KM,Kg.isBefore=qM,Kg.isBetween=_M,Kg.isSame=$M,Kg.isSameOrAfter=At,Kg.isSameOrBefore=Mt,Kg.isValid=yt,Kg.lang=Xg,Kg.locale=Ct,Kg.localeData=ct,Kg.max=fg,Kg.min=Fg,Kg.parsingFlags=ut,Kg.set=v,Kg.startOf=Dt,Kg.subtract=bg,Kg.toArray=st,Kg.toObject=xt,Kg.toDate=rt,Kg.toISOString=et,Kg.inspect=it,Kg.toJSON=jt,Kg.toString=gt,Kg.unix=Qt,Kg.valueOf=Bt,Kg.creationData=Lt,Kg.year=Bg,Kg.isLeapYear=rA,Kg.weekYear=Yt,Kg.isoWeekYear=dt,Kg.quarter=Kg.quarters=Ut,Kg.month=nA,Kg.daysInMonth=CA,Kg.week=Kg.weeks=dA,Kg.isoWeek=Kg.isoWeeks=hA,Kg.weeksInYear=St,Kg.isoWeeksInYear=ht,Kg.date=vg,Kg.day=Kg.days=fA,Kg.weekday=kA,Kg.isoWeekday=RA,Kg.dayOfYear=Ot,Kg.hour=Kg.hours=lg,Kg.minute=Kg.minutes=Wg,Kg.second=Kg.seconds=Vg,Kg.millisecond=Kg.milliseconds=Zg,Kg.utcOffset=SM,Kg.utc=pM,Kg.local=UM,Kg.parseZone=OM,Kg.hasAlignedHourOffset=mM,Kg.isDST=FM,Kg.isLocal=kM,Kg.isUtcOffset=RM,Kg.isUtc=JM,Kg.isUTC=JM,Kg.zoneAbbr=Ft,Kg.zoneName=ft,Kg.dates=w("dates accessor is deprecated. Use date instead.",vg),Kg.months=w("months accessor is deprecated. Use month instead",nA),Kg.years=w("years accessor is deprecated. Use year instead",Bg),Kg.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",zM),Kg.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",fM);var qg=h.prototype;qg.calendar=S,qg.longDateFormat=z,qg.invalidDate=p,qg.ordinal=U,qg.preparse=Jt,qg.postformat=Jt,qg.relativeTime=O,qg.pastFuture=m,qg.set=Y,qg.months=iA,qg.monthsShort=TA,qg.monthsParse=NA,qg.monthsRegex=DA,qg.monthsShortRegex=cA,qg.week=LA,qg.firstDayOfYear=YA,qg.firstDayOfWeek=lA,qg.weekdays=pA,qg.weekdaysMin=OA,qg.weekdaysShort=UA,qg.weekdaysParse=FA,qg.weekdaysRegex=JA,qg.weekdaysShortRegex=GA,qg.weekdaysMinRegex=HA,qg.isPM=PA,qg.meridiem=ZA,$A("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(A){var M=A%10,t=1===j(A%100/10)?"th":1===M?"st":2===M?"nd":3===M?"rd":"th";return A+t}}),M.lang=w("moment.lang is deprecated. Use moment.locale instead.",$A),M.langData=w("moment.langData is deprecated. Use moment.localeData instead.",tM);var _g=Math.abs,$g=eI("ms"),Ae=eI("s"),Me=eI("m"),te=eI("h"),Ie=eI("d"),ge=eI("w"),ee=eI("M"),ie=eI("y"),Te=TI("milliseconds"),Ee=TI("seconds"),Ne=TI("minutes"),oe=TI("hours"),ne=TI("days"),Ce=TI("months"),ce=TI("years"),De=Math.round,ae={s:45,m:45,h:22,d:26,M:11},Be=Math.abs,Qe=uM.prototype;return Qe.abs=Zt,Qe.add=qt,Qe.subtract=_t,Qe.as=II,Qe.asMilliseconds=$g,Qe.asSeconds=Ae,Qe.asMinutes=Me,Qe.asHours=te,Qe.asDays=Ie,Qe.asWeeks=ge,Qe.asMonths=ee,Qe.asYears=ie,Qe.valueOf=gI,Qe._bubble=AI,Qe.get=iI,Qe.milliseconds=Te,Qe.seconds=Ee,Qe.minutes=Ne,Qe.hours=oe,Qe.days=ne,Qe.weeks=EI,Qe.months=Ce,Qe.years=ce,Qe.humanize=cI,Qe.toISOString=DI,Qe.toString=DI,Qe.toJSON=DI,Qe.locale=Ct,Qe.localeData=ct,Qe.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",DI),Qe.lang=Xg,V("X",0,0,"unix"),V("x",0,0,"valueOf"),_("x",PI),_("X",qI),tA("X",function(A,M,t){t._d=new Date(1e3*parseFloat(A,10))}),tA("x",function(A,M,t){t._d=new Date(j(A))}),M.version="2.17.1",t(sM),M.fn=Kg,M.min=jM,M.max=yM,M.now=kg,M.utc=n,M.unix=kt,M.months=Xt,M.isDate=T,M.locale=$A,M.invalid=a,M.duration=GM,M.isMoment=s,M.weekdays=Wt,M.parseZone=Rt,M.localeData=tM,M.isDuration=wM,M.monthsShort=vt,M.weekdaysMin=Pt,M.defineLocale=AM,M.updateLocale=MM,M.locales=IM,M.weekdaysShort=Vt,M.normalizeUnits=f,M.relativeTimeRounding=nI,M.relativeTimeThreshold=CI,M.calendarFormat=VM,M.prototype=Kg,M})}).call(M,t(128)(A))},function(A,M,t){"use strict";var I=t(132).default,g=t(133).default,e=t(78).default;M.__esModule=!0;var i=function(A){return I(g({values:function(){var A=this;return e(this).map(function(M){return A[M]})}}),A)},T={SIZES:{large:"lg",medium:"md",small:"sm",xsmall:"xs",lg:"lg",md:"md",sm:"sm",xs:"xs"},GRID_COLUMNS:12},E=i({LARGE:"large",MEDIUM:"medium",SMALL:"small",XSMALL:"xsmall"});M.Sizes=E;var N=i({SUCCESS:"success",WARNING:"warning",DANGER:"danger",INFO:"info"});M.State=N;var o="default";M.DEFAULT=o;var n="primary";M.PRIMARY=n;var C="link";M.LINK=C;var c="inverse";M.INVERSE=c,M.default=T},function(A,M){"use strict";function t(){for(var A=arguments.length,M=Array(A),t=0;t0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURI(o))):"("===E?g+=1:")"===E?g-=1:":"===E.charAt(0)?(N=E.substring(1),o=M[N],null!=o||g>0?void 0:(0,C.default)(!1),null!=o&&(e+=encodeURIComponent(o))):e+=E;return e.replace(/\/+/g,"/")}M.__esModule=!0,M.compilePattern=i,M.matchPattern=T,M.getParamNames=E,M.getParams=N,M.formatPattern=o;var n=t(8),C=I(n),c=Object.create(null)},function(A,M){"use strict";M.__esModule=!0;var t="PUSH";M.PUSH=t;var I="REPLACE";M.REPLACE=I;var g="POP";M.POP=g,M.default={PUSH:t,REPLACE:I,POP:g}},function(A,M,t){"use strict";function I(A,M){return(A&M)===M}var g=t(2),e={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(A){var M=e,t=A.Properties||{},i=A.DOMAttributeNamespaces||{},E=A.DOMAttributeNames||{},N=A.DOMPropertyNames||{},o=A.DOMMutationMethods||{};A.isCustomAttribute&&T._isCustomAttributeFunctions.push(A.isCustomAttribute);for(var n in t){T.properties.hasOwnProperty(n)?g(!1):void 0;var C=n.toLowerCase(),c=t[n],D={attributeName:C,attributeNamespace:null,propertyName:n,mutationMethod:null,mustUseAttribute:I(c,M.MUST_USE_ATTRIBUTE),mustUseProperty:I(c,M.MUST_USE_PROPERTY),hasSideEffects:I(c,M.HAS_SIDE_EFFECTS),hasBooleanValue:I(c,M.HAS_BOOLEAN_VALUE),hasNumericValue:I(c,M.HAS_NUMERIC_VALUE),hasPositiveNumericValue:I(c,M.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:I(c,M.HAS_OVERLOADED_BOOLEAN_VALUE)};if(D.mustUseAttribute&&D.mustUseProperty?g(!1):void 0,!D.mustUseProperty&&D.hasSideEffects?g(!1):void 0,D.hasBooleanValue+D.hasNumericValue+D.hasOverloadedBooleanValue<=1?void 0:g(!1),E.hasOwnProperty(n)){var a=E[n];D.attributeName=a}i.hasOwnProperty(n)&&(D.attributeNamespace=i[n]),N.hasOwnProperty(n)&&(D.propertyName=N[n]),o.hasOwnProperty(n)&&(D.mutationMethod=o[n]),T.properties[n]=D}}},i={},T={ID_ATTRIBUTE_NAME:"data-reactid",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(A){for(var M=0;M1){var M=A.indexOf(c,1);return M>-1?A.substr(0,M):A}return null},traverseEnterLeave:function(A,M,t,I,g){var e=N(A,M);e!==A&&o(A,e,t,I,!1,!0),e!==M&&o(e,M,t,g,!0,!1)},traverseTwoPhase:function(A,M,t){A&&(o("",A,M,t,!0,!1),o(A,"",M,t,!1,!0))},traverseTwoPhaseSkipTarget:function(A,M,t){A&&(o("",A,M,t,!0,!0),o(A,"",M,t,!0,!0))},traverseAncestors:function(A,M,t){o("",A,M,t,!0,!1)},getFirstCommonAncestorID:N,_getNextDescendantID:E,isAncestorIDOf:i,SEPARATOR:c};A.exports=B},function(A,M){var t=A.exports={version:"1.2.6"};"number"==typeof __e&&(__e=t)},function(A,M,t){"use strict";var I={};A.exports=I},function(A,M,t){"use strict";function I(A,M,t){var I=0;return n.default.Children.map(A,function(A){if(n.default.isValidElement(A)){var g=I;return I++,M.call(t,A,g)}return A})}function g(A,M,t){var I=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I),I++)})}function e(A){var M=0;return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&M++}),M}function i(A){var M=!1;return n.default.Children.forEach(A,function(A){!M&&n.default.isValidElement(A)&&(M=!0)}),M}function T(A,M){var t=void 0;return g(A,function(I,g){!t&&M(I,g,A)&&(t=I)}),t}function E(A,M,t){var I=0,g=[];return n.default.Children.forEach(A,function(A){n.default.isValidElement(A)&&(M.call(t,A,I)&&g.push(A),I++)}),g}var N=t(6).default;M.__esModule=!0;var o=t(1),n=N(o);M.default={map:I,forEach:g,numberOf:e,find:T,findValidComponents:E,hasValidComponent:i},A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0}),M.default=function(A){return(0,T.default)(e.default.findDOMNode(A))};var g=t(16),e=I(g),i=t(39),T=I(i);A.exports=M.default},function(A,M,t){"use strict";var I=t(204),g=t(437),e=t(217),i=t(226),T=t(227),E=t(2),N=(t(3),{}),o=null,n=function(A,M){A&&(g.executeDispatchesInOrder(A,M),A.isPersistent()||A.constructor.release(A))},C=function(A){return n(A,!0)},c=function(A){return n(A,!1)},D=null,a={injection:{injectMount:g.injection.injectMount,injectInstanceHandle:function(A){D=A},getInstanceHandle:function(){return D},injectEventPluginOrder:I.injectEventPluginOrder,injectEventPluginsByName:I.injectEventPluginsByName},eventNameDispatchConfigs:I.eventNameDispatchConfigs,registrationNameModules:I.registrationNameModules,putListener:function(A,M,t){"function"!=typeof t?E(!1):void 0;var g=N[M]||(N[M]={});g[A]=t;var e=I.registrationNameModules[M];e&&e.didPutListener&&e.didPutListener(A,M,t)},getListener:function(A,M){var t=N[M];return t&&t[A]},deleteListener:function(A,M){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M);var g=N[M];g&&delete g[A]},deleteAllListeners:function(A){for(var M in N)if(N[M][A]){var t=I.registrationNameModules[M];t&&t.willDeleteListener&&t.willDeleteListener(A,M),delete N[M][A]}},extractEvents:function(A,M,t,g,e){for(var T,E=I.plugins,N=0;N1?I-1:0),e=1;e":">","<":"<",'"':""","'":"'"},e=/[&><"']/g;A.exports=I},function(A,M,t){"use strict";var I=t(10),g=/^[ \r\n\t\f]/,e=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,i=function(A,M){A.innerHTML=M};if("undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction&&(i=function(A,M){MSApp.execUnsafeLocalFunction(function(){A.innerHTML=M})}),I.canUseDOM){var T=document.createElement("div");T.innerHTML=" ",""===T.innerHTML&&(i=function(A,M){if(A.parentNode&&A.parentNode.replaceChild(A,A),g.test(M)||"<"===M[0]&&e.test(M)){A.innerHTML=String.fromCharCode(65279)+M;var t=A.firstChild;1===t.data.length?A.removeChild(t):t.deleteData(0,1)}else A.innerHTML=M})}A.exports=i},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}Object.defineProperty(M,"__esModule",{value:!0});var g=t(1),e=I(g),i=function(A){var M=A.label,t=A.id,I=A.name,g=A.value,i=A.onChange,T=A.type,E=A.spellCheck,N=A.required,o=A.readonly,n=A.autoComplete,C=A.align,c=A.className,D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n});return o&&(D=e.default.createElement("input",{id:t,name:I,value:g,onChange:i,className:"ig-text",type:T,spellCheck:E,required:N,autoComplete:n,disabled:!0})),e.default.createElement("div",{className:"input-group "+C+" "+c},D,e.default.createElement("i",{className:"ig-helpers"}),e.default.createElement("label",{className:"ig-label"},M))};M.default=i},function(A,M,t){A.exports={default:t(259),__esModule:!0}},function(A,M,t){var I=t(265),g=t(49),e=t(134),i="prototype",T=function(A,M,t){var E,N,o,n=A&T.F,C=A&T.G,c=A&T.S,D=A&T.P,a=A&T.B,B=A&T.W,Q=C?g:g[M]||(g[M]={}),r=C?I:c?I[M]:(I[M]||{})[i];C&&(t=M);for(E in t)N=!n&&r&&E in r,N&&E in Q||(o=N?r[E]:t[E],Q[E]=C&&"function"!=typeof r[E]?t[E]:a&&N?e(o,I):B&&r[E]==o?function(A){var M=function(M){return this instanceof A?new A(M):A(M)};return M[i]=A[i],M}(o):D&&"function"==typeof o?e(Function.call,o):o,D&&((Q[i]||(Q[i]={}))[E]=o))};T.F=1,T.G=2,T.S=4,T.P=8,T.B=16,T.W=32,A.exports=T},function(A,M){var t=Object;A.exports={create:t.create,getProto:t.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:t.getOwnPropertyDescriptor,setDesc:t.defineProperty,setDescs:t.defineProperties,getKeys:t.keys,getNames:t.getOwnPropertyNames,getSymbols:t.getOwnPropertySymbols,each:[].forEach}},function(A,M,t){"use strict";var I=t(32),g=function(){};I&&(g=function(){return document.addEventListener?function(A,M,t,I){return A.addEventListener(M,t,I||!1)}:document.attachEvent?function(A,M,t){return A.attachEvent("on"+M,t)}:void 0}()),A.exports=g},function(A,M,t){"use strict";var I=t(145),g=t(295),e=t(290),i=t(291),T=Object.prototype.hasOwnProperty;A.exports=function(A,M,t){var E="",N=M;if("string"==typeof M){if(void 0===t)return A.style[I(M)]||e(A).getPropertyValue(g(M));(N={})[M]=t}for(var o in N)T.call(N,o)&&(N[o]||0===N[o]?E+=g(o)+":"+N[o]+";":i(A,g(o)));A.style.cssText+=";"+E}},function(A,M,t){(function(){var t=this,I=t.humanize,g={};"undefined"!=typeof A&&A.exports&&(M=A.exports=g),M.humanize=g,g.noConflict=function(){return t.humanize=I,this},g.pad=function(A,M,t,I){if(A+="",t?t.length>1&&(t=t.charAt(0)):t=" ",I=void 0===I?"left":"right","right"===I)for(;A.length4&&A<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th"},w:function(){return t.getDay()},z:function(){return(o.L()?i[o.n()]:e[o.n()])+o.j()-1},W:function(){var A=o.z()-o.N()+1.5;return g.pad(1+Math.floor(Math.abs(A)/7)+(A%7>3.5?1:0),2,"0")},F:function(){return N[t.getMonth()]},m:function(){return g.pad(o.n(),2,"0")},M:function(){return o.F().slice(0,3)},n:function(){return t.getMonth()+1},t:function(){return new Date(o.Y(),o.n(),0).getDate()},L:function(){return 1===new Date(o.Y(),1,29).getMonth()?1:0},o:function(){var A=o.n(),M=o.W();return o.Y()+(12===A&&M<9?-1:1===A&&M>9)},Y:function(){return t.getFullYear()},y:function(){return String(o.Y()).slice(-2)},a:function(){return t.getHours()>11?"pm":"am"},A:function(){return o.a().toUpperCase()},B:function(){var A=t.getTime()/1e3,M=A%86400+3600;M<0&&(M+=86400);var I=M/86.4%1e3;return A<0?Math.ceil(I):Math.floor(I)},g:function(){return o.G()%12||12},G:function(){return t.getHours()},h:function(){return g.pad(o.g(),2,"0")},H:function(){return g.pad(o.G(),2,"0")},i:function(){return g.pad(t.getMinutes(),2,"0")},s:function(){return g.pad(t.getSeconds(),2,"0")},u:function(){return g.pad(1e3*t.getMilliseconds(),6,"0")},O:function(){var A=t.getTimezoneOffset(),M=Math.abs(A);return(A>0?"-":"+")+g.pad(100*Math.floor(M/60)+M%60,4,"0")},P:function(){var A=o.O();return A.substr(0,3)+":"+A.substr(3,2)},Z:function(){return 60*-t.getTimezoneOffset()},c:function(){return"Y-m-d\\TH:i:sP".replace(I,T)},r:function(){return"D, d M Y H:i:s O".replace(I,T)},U:function(){return t.getTime()/1e3||0}};return A.replace(I,T)},g.numberFormat=function(A,M,t,I){M=isNaN(M)?2:Math.abs(M),t=void 0===t?".":t,I=void 0===I?",":I;var g=A<0?"-":"";A=Math.abs(+A||0);var e=parseInt(A.toFixed(M),10)+"",i=e.length>3?e.length%3:0;return g+(i?e.substr(0,i)+I:"")+e.substr(i).replace(/(\d{3})(?=\d)/g,"$1"+I)+(M?t+Math.abs(A-e).toFixed(M).slice(2):"")},g.naturalDay=function(A,M){A=void 0===A?g.time():A,M=void 0===M?"Y-m-d":M;var t=86400,I=new Date,e=new Date(I.getFullYear(),I.getMonth(),I.getDate()).getTime()/1e3;return A=e-t?"yesterday":A>=e&&A=e+t&&A-2)return(t>=0?"just ":"")+"now";if(t<60&&t>-60)return t>=0?Math.floor(t)+" seconds ago":"in "+Math.floor(-t)+" seconds";if(t<120&&t>-120)return t>=0?"about a minute ago":"in about a minute";if(t<3600&&t>-3600)return t>=0?Math.floor(t/60)+" minutes ago":"in "+Math.floor(-t/60)+" minutes";if(t<7200&&t>-7200)return t>=0?"about an hour ago":"in about an hour";if(t<86400&&t>-86400)return t>=0?Math.floor(t/3600)+" hours ago":"in "+Math.floor(-t/3600)+" hours";var I=172800;if(t-I)return t>=0?"1 day ago":"in 1 day";var e=2505600;if(t-e)return t>=0?Math.floor(t/86400)+" days ago":"in "+Math.floor(-t/86400)+" days";var i=5184e3;if(t-i)return t>=0?"about a month ago":"in about a month";var T=parseInt(g.date("Y",M),10),E=parseInt(g.date("Y",A),10),N=12*T+parseInt(g.date("n",M),10),o=12*E+parseInt(g.date("n",A),10),n=N-o;if(n<12&&n>-12)return n>=0?n+" months ago":"in "+-n+" months";var C=T-E;return C<2&&C>-2?C>=0?"a year ago":"in a year":C>=0?C+" years ago":"in "+-C+" years"},g.ordinal=function(A){A=parseInt(A,10),A=isNaN(A)?0:A;var M=A<0?"-":"";A=Math.abs(A);var t=A%100;return M+A+(t>4&&t<21?"th":{1:"st",2:"nd",3:"rd"}[A%10]||"th")},g.filesize=function(A,M,t,I,e,i){return M=void 0===M?1024:M,A<=0?"0 bytes":(A

    "),A=A.replace(/\n/g,"
    "),"

    "+A+"

    "},g.nl2br=function(A){return A.replace(/(\r\n|\n|\r)/g,"
    ")},g.truncatechars=function(A,M){return A.length<=M?A:A.substr(0,M)+"…"},g.truncatewords=function(A,M){var t=A.split(" ");return t.length0,Q=C.enumErrorProps&&(A===u||A instanceof Error),r=C.enumPrototypes&&T(A);++IM.documentElement.clientHeight;return{modalStyles:{paddingRight:I&&!g?Q.default():void 0,paddingLeft:!I&&g?Q.default():void 0}}}});X.Body=z.default,X.Header=U.default,X.Title=m.default,X.Footer=f.default,X.Dialog=h.default,X.TRANSITION_DURATION=300,X.BACKDROP_TRANSITION_DURATION=150,M.default=c.bsSizes([a.Sizes.LARGE,a.Sizes.SMALL],c.bsClass("modal",X)),A.exports=M.default},function(A,M,t){"use strict";var I=t(15).default,g=t(14).default,e=t(38).default,i=t(7).default,T=t(6).default;M.__esModule=!0;var E=t(1),N=T(E),o=t(5),n=T(o),C=t(11),c=T(C),D=t(44),a=T(D),B=function(A){function M(){g(this,M),A.apply(this,arguments)}return I(M,A),M.prototype.render=function(){var A=this.props,M=A["aria-label"],t=e(A,["aria-label"]),I=a.default(this.context.$bs_onModalHide,this.props.onHide);return N.default.createElement("div",i({},t,{className:n.default(this.props.className,c.default.prefix(this.props,"header"))}),this.props.closeButton&&N.default.createElement("button",{type:"button",className:"close","aria-label":M,onClick:I},N.default.createElement("span",{"aria-hidden":"true" +},"×")),this.props.children)},M}(N.default.Component);B.propTypes={"aria-label":N.default.PropTypes.string,bsClass:N.default.PropTypes.string,closeButton:N.default.PropTypes.bool,onHide:N.default.PropTypes.func},B.contextTypes={$bs_onModalHide:N.default.PropTypes.func},B.defaultProps={"aria-label":"Close",closeButton:!1},M.default=C.bsClass("modal",B),A.exports=M.default},function(A,M,t){"use strict";function I(A,M){return Array.isArray(M)?M.indexOf(A)>=0:A===M}var g=t(7).default,e=t(78).default,i=t(6).default;M.__esModule=!0;var T=t(40),E=i(T),N=t(170),o=i(N),n=t(1),C=i(n),c=t(16),D=i(c),a=t(127),B=(i(a),t(370)),Q=i(B),r=t(44),s=i(r),x=C.default.createClass({displayName:"OverlayTrigger",propTypes:g({},Q.default.propTypes,{trigger:C.default.PropTypes.oneOfType([C.default.PropTypes.oneOf(["click","hover","focus"]),C.default.PropTypes.arrayOf(C.default.PropTypes.oneOf(["click","hover","focus"]))]),delay:C.default.PropTypes.number,delayShow:C.default.PropTypes.number,delayHide:C.default.PropTypes.number,defaultOverlayShown:C.default.PropTypes.bool,overlay:C.default.PropTypes.node.isRequired,onBlur:C.default.PropTypes.func,onClick:C.default.PropTypes.func,onFocus:C.default.PropTypes.func,onMouseEnter:C.default.PropTypes.func,onMouseLeave:C.default.PropTypes.func,target:function(){},onHide:function(){},show:function(){}}),getDefaultProps:function(){return{defaultOverlayShown:!1,trigger:["hover","focus"]}},getInitialState:function(){return{isOverlayShown:this.props.defaultOverlayShown}},show:function(){this.setState({isOverlayShown:!0})},hide:function(){this.setState({isOverlayShown:!1})},toggle:function(){this.state.isOverlayShown?this.hide():this.show()},componentWillMount:function(){this.handleMouseOver=this.handleMouseOverOut.bind(null,this.handleDelayedShow),this.handleMouseOut=this.handleMouseOverOut.bind(null,this.handleDelayedHide)},componentDidMount:function(){this._mountNode=document.createElement("div"),this.renderOverlay()},renderOverlay:function(){D.default.unstable_renderSubtreeIntoContainer(this,this._overlay,this._mountNode)},componentWillUnmount:function(){D.default.unmountComponentAtNode(this._mountNode),this._mountNode=null,clearTimeout(this._hoverShowDelay),clearTimeout(this._hoverHideDelay)},componentDidUpdate:function(){this._mountNode&&this.renderOverlay()},getOverlayTarget:function(){return D.default.findDOMNode(this)},getOverlay:function(){var A=g({},o.default(this.props,e(Q.default.propTypes)),{show:this.state.isOverlayShown,onHide:this.hide,target:this.getOverlayTarget,onExit:this.props.onExit,onExiting:this.props.onExiting,onExited:this.props.onExited,onEnter:this.props.onEnter,onEntering:this.props.onEntering,onEntered:this.props.onEntered}),M=n.cloneElement(this.props.overlay,{placement:A.placement,container:A.container});return C.default.createElement(Q.default,A,M)},render:function(){var A=C.default.Children.only(this.props.children),M=A.props,t={"aria-describedby":this.props.overlay.props.id};return this._overlay=this.getOverlay(),t.onClick=s.default(M.onClick,this.props.onClick),I("click",this.props.trigger)&&(t.onClick=s.default(this.toggle,t.onClick)),I("hover",this.props.trigger)&&(t.onMouseOver=s.default(this.handleMouseOver,this.props.onMouseOver,M.onMouseOver),t.onMouseOut=s.default(this.handleMouseOut,this.props.onMouseOut,M.onMouseOut)),I("focus",this.props.trigger)&&(t.onFocus=s.default(this.handleDelayedShow,this.props.onFocus,M.onFocus),t.onBlur=s.default(this.handleDelayedHide,this.props.onBlur,M.onBlur)),n.cloneElement(A,t)},handleDelayedShow:function(){var A=this;if(null!=this._hoverHideDelay)return clearTimeout(this._hoverHideDelay),void(this._hoverHideDelay=null);if(!this.state.isOverlayShown&&null==this._hoverShowDelay){var M=null!=this.props.delayShow?this.props.delayShow:this.props.delay;return M?void(this._hoverShowDelay=setTimeout(function(){A._hoverShowDelay=null,A.show()},M)):void this.show()}},handleDelayedHide:function(){var A=this;if(null!=this._hoverShowDelay)return clearTimeout(this._hoverShowDelay),void(this._hoverShowDelay=null);if(this.state.isOverlayShown&&null==this._hoverHideDelay){var M=null!=this.props.delayHide?this.props.delayHide:this.props.delay;return M?void(this._hoverHideDelay=setTimeout(function(){A._hoverHideDelay=null,A.hide()},M)):void this.hide()}},handleMouseOverOut:function(A,M){var t=M.currentTarget,I=M.relatedTarget||M.nativeEvent.toElement;I&&(I===t||E.default(t,I))||A(M)}});M.default=x,A.exports=M.default},function(A,M,t){"use strict";var I=t(7).default,g=t(6).default;M.__esModule=!0;var e=t(1),i=g(e),T=t(5),E=g(T),N=t(11),o=g(N),n=t(183),C=g(n),c=i.default.createClass({displayName:"Tooltip",propTypes:{id:C.default(i.default.PropTypes.oneOfType([i.default.PropTypes.string,i.default.PropTypes.number])),placement:i.default.PropTypes.oneOf(["top","right","bottom","left"]),positionLeft:i.default.PropTypes.number,positionTop:i.default.PropTypes.number,arrowOffsetLeft:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),arrowOffsetTop:i.default.PropTypes.oneOfType([i.default.PropTypes.number,i.default.PropTypes.string]),title:i.default.PropTypes.node},getDefaultProps:function(){return{bsClass:"tooltip",placement:"right"}},render:function(){var A,M=(A={},A[o.default.prefix(this.props)]=!0,A[this.props.placement]=!0,A),t=I({left:this.props.positionLeft,top:this.props.positionTop},this.props.style),g={left:this.props.arrowOffsetLeft,top:this.props.arrowOffsetTop};return i.default.createElement("div",I({role:"tooltip"},this.props,{className:E.default(this.props.className,M),style:t}),i.default.createElement("div",{className:o.default.prefix(this.props,"arrow"),style:g}),i.default.createElement("div",{className:o.default.prefix(this.props,"inner")},this.props.children))}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){return A="function"==typeof A?A():A,i.default.findDOMNode(A)||M}Object.defineProperty(M,"__esModule",{value:!0}),M.default=g;var e=t(16),i=I(e);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement. You can usually obtain a ReactComponent or DOMElement from a ReactElement by attaching a ref to it."):"object"===E&&"function"==typeof i.render||1===i.nodeType?null:new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected a ReactComponent or a ")+"DOMElement.")}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M,t){"use strict";function I(){function A(A,M,I){for(var g=0;g>",null!=t[I]?A(t,I,g):M?new Error("Required prop '"+I+"' was not specified in '"+g+"'."):void 0}var t=M.bind(null,!1);return t.isRequired=M.bind(null,!0),t}M.__esModule=!0,M.errMsg=t,M.createChainableTypeChecker=I},function(A,M){"use strict";function t(A,M,t){function I(){return i=!0,T?void(N=[].concat(Array.prototype.slice.call(arguments))):void t.apply(this,arguments)}function g(){if(!i&&(E=!0,!T)){for(T=!0;!i&&e=A&&E&&(i=!0,t()))}}var e=0,i=!1,T=!1,E=!1,N=void 0;g()}function I(A,M,t){function I(A,M,I){i||(M?(i=!0,t(M)):(e[A]=I,i=++T===g,i&&t(null,e)))}var g=A.length,e=[];if(0===g)return t(null,e);var i=!1,T=0;A.forEach(function(A,t){M(A,t,function(A,M){I(t,A,M)})})}M.__esModule=!0,M.loopAsync=t,M.mapAsync=I},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0,M.router=M.routes=M.route=M.components=M.component=M.location=M.history=M.falsy=M.locationShape=M.routerShape=void 0;var e=t(1),i=t(66),T=(g(i),t(34)),E=I(T),N=t(9),o=(g(N),e.PropTypes.func),n=e.PropTypes.object,C=e.PropTypes.shape,c=e.PropTypes.string,D=M.routerShape=C({push:o.isRequired,replace:o.isRequired,go:o.isRequired,goBack:o.isRequired,goForward:o.isRequired,setRouteLeaveHook:o.isRequired,isActive:o.isRequired}),a=M.locationShape=C({pathname:c.isRequired,search:c.isRequired,state:n,action:c.isRequired,key:c}),B=M.falsy=E.falsy,Q=M.history=E.history,r=M.location=a,s=M.component=E.component,x=M.components=E.components,j=M.route=E.route,y=(M.routes=E.routes,M.router=D),u={falsy:B,history:Q,location:r,component:s,components:x,route:j,router:y};M.default=u},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!0;return!1}function e(A,M){function t(M){var t=!(arguments.length<=1||void 0===arguments[1])&&arguments[1],I=arguments.length<=2||void 0===arguments[2]?null:arguments[2],g=void 0;return t&&t!==!0||null!==I?(M={pathname:M,query:t},g=I||!1):(M=A.createLocation(M),g=t),(0,C.default)(M,g,s.location,s.routes,s.params)}function I(A,t){x&&x.location===A?e(x,t):(0,B.default)(M,A,function(M,I){M?t(M):I?e(i({},I,{location:A}),t):t()})}function e(A,M){function t(t,g){return t||g?I(t,g):void(0,D.default)(A,function(t,I){t?M(t):M(null,null,s=i({},A,{components:I}))})}function I(A,t){A?M(A):M(null,t)}var g=(0,N.default)(s,A),e=g.leaveRoutes,T=g.changeRoutes,E=g.enterRoutes;(0,o.runLeaveHooks)(e,s),e.filter(function(A){return E.indexOf(A)===-1}).forEach(a),(0,o.runChangeHooks)(T,s,A,function(M,g){return M||g?I(M,g):void(0,o.runEnterHooks)(E,A,t)})}function T(A){var M=arguments.length<=1||void 0===arguments[1]||arguments[1];return A.__id__||M&&(A.__id__=j++)}function E(A){return A.reduce(function(A,M){return A.push.apply(A,y[T(M)]),A},[])}function n(A,t){(0,B.default)(M,A,function(M,I){if(null==I)return void t();x=i({},I,{location:A});for(var g=E((0,N.default)(s,x).leaveRoutes),e=void 0,T=0,o=g.length;null==e&&T=32||13===M?M:0}A.exports=t},function(A,M){"use strict";function t(A){var M=this,t=M.nativeEvent;if(t.getModifierState)return t.getModifierState(A);var I=g[A];return!!I&&!!t[I]}function I(A){return t}var g={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};A.exports=I},function(A,M){"use strict";function t(A){var M=A.target||A.srcElement||window;return 3===M.nodeType?M.parentNode:M}A.exports=t},function(A,M){"use strict";function t(A){var M=A&&(I&&A[I]||A[g]);if("function"==typeof M)return M}var I="function"==typeof Symbol&&Symbol.iterator,g="@@iterator";A.exports=t},function(A,M,t){"use strict";function I(A){return"function"==typeof A&&"undefined"!=typeof A.prototype&&"function"==typeof A.prototype.mountComponent&&"function"==typeof A.prototype.receiveComponent}function g(A){var M;if(null===A||A===!1)M=new i(g);else if("object"==typeof A){var t=A;!t||"function"!=typeof t.type&&"string"!=typeof t.type?N(!1):void 0,M="string"==typeof t.type?T.createInternalComponent(t):I(t.type)?new t.type(t):new o}else"string"==typeof A||"number"==typeof A?M=T.createInstanceForText(A):N(!1);return M.construct(A),M._mountIndex=0,M._mountImage=null,M}var e=t(443),i=t(215),T=t(221),E=t(4),N=t(2),o=(t(3),function(){});E(o.prototype,e.Mixin,{_instantiateReactComponent:g}),A.exports=g},function(A,M,t){"use strict";/** * Checks if an event is supported in the current execution environment. * * NOTE: This will not work correctly for non-generic events such as ` + "`" + `change` + "`" + `, @@ -200,7 +200,7 @@ bsClass:N.default.PropTypes.string,closeButton:N.default.PropTypes.bool,onHide:N * @internal * @license Modernizr 3.0.0pre (Custom Build) | MIT */ -function I(A,M){if(!e.canUseDOM||M&&!("addEventListener"in document))return!1;var t="on"+A,I=t in document;if(!I){var i=document.createElement("div");i.setAttribute(t,"return;"),I="function"==typeof i[t]}return!I&&g&&"wheel"===A&&(I=document.implementation.hasFeature("Events.wheel","3.0")),I}var g,e=t(10);e.canUseDOM&&(g=document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("","")!==!0),A.exports=I},function(A,M,t){"use strict";var I=t(10),g=t(75),e=t(76),i=function(A,M){A.textContent=M};I.canUseDOM&&("textContent"in document.documentElement||(i=function(A,M){e(A,g(M))})),A.exports=i},function(A,M){"use strict";function t(A,M){var t=null===A||A===!1,I=null===M||M===!1;if(t||I)return t===I;var g=typeof A,e=typeof M;return"string"===g||"number"===g?"string"===e||"number"===e:"object"===e&&A.type===M.type&&A.key===M.key}A.exports=t},function(A,M,t){"use strict";function I(A){return a[A]}function g(A,M){return A&&null!=A.key?i(A.key):M.toString(36)}function e(A){return(""+A).replace(B,I)}function i(A){return"$"+e(A)}function T(A,M,t,I){var e=typeof A;if("undefined"!==e&&"boolean"!==e||(A=null),null===A||"string"===e||"number"===e||N.isValidElement(A))return t(I,A,""===M?c+g(A,0):M),1;var E,o,a=0,B=""===M?c:M+D;if(Array.isArray(A))for(var Q=0;QM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;iM.name.toLowerCase()?1:0}),g=g.sort(function(A,M){return A.name.toLowerCase()M.name.toLowerCase()?1:0}),M&&(t=t.reverse(),g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsBySize=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return A.size-M.size}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.sortObjectsByDate=function(A,M){var t=A.filter(function(A){return A.name.endsWith("/")}),g=A.filter(function(A){return!A.name.endsWith("/")});return g=g.sort(function(A,M){return new Date(A.lastModified).getTime()-new Date(M.lastModified).getTime()}),M&&(g=g.reverse()),[].concat(I(t),I(g))},M.pathSlice=function(A){A=A.replace(g.minioBrowserPrefix,"");var M="",t="";if(!A)return{bucket:t,prefix:M};var I=A.indexOf("/",1);return I==-1?(t=A.slice(1),{bucket:t,prefix:M}):(t=A.slice(1,I),M=A.slice(I+1),{bucket:t,prefix:M})},M.pathJoin=function(A,M){return M||(M=""),g.minioBrowserPrefix+"/"+A+"/"+M}},function(A,M,t){"use strict";function I(A){if(A&&A.__esModule)return A;var M={};if(null!=A)for(var t in A)Object.prototype.hasOwnProperty.call(A,t)&&(M[t]=A[t]);return M.default=A,M}function g(A){return A&&A.__esModule?A:{default:A}}function e(A,M){if(!(A instanceof M))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(M,"__esModule",{value:!0});var i=function(){function A(A,M){for(var t=0;t":i.innerHTML="<"+A+">",T[A]=!i.firstChild),T[A]?C[A]:null}var g=t(10),e=t(2),i=g.canUseDOM?document.createElement("div"):null,T={},E=[1,'"],N=[1,"","
    "],o=[3,"","
    "],n=[1,'',""],C={"*":[1,"?
    ","
    "],area:[1,"",""],col:[2,"","
    "],legend:[1,"
    ","
    "],param:[1,"",""],tr:[2,"","
    "],optgroup:E,option:E,caption:N,colgroup:N,tbody:N,tfoot:N,thead:N,td:o,th:o},c=["circle","clipPath","defs","ellipse","g","image","line","linearGradient","mask","path","pattern","polygon","polyline","radialGradient","rect","stop","text","tspan"];c.forEach(function(A){C[A]=n,T[A]=!0}),A.exports=I},function(A,M){"use strict";function t(A,M){if(A===M)return!0;if("object"!=typeof A||null===A||"object"!=typeof M||null===M)return!1;var t=Object.keys(A),g=Object.keys(M);if(t.length!==g.length)return!1;for(var e=I.bind(M),i=0;i-1&&A%1==0&&A1)for(var t=1;tA.clientHeight}Object.defineProperty(M,"__esModule",{value:!0}),M.default=i;var T=t(57),E=I(T),N=t(39),o=I(N);A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M,t,I,g){var i=A[M],E="undefined"==typeof i?"undefined":e(i);return T.default.isValidElement(i)?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of type ReactElement "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):"function"!==E&&"string"!==E?new Error("Invalid "+I+" ` + "`" + `"+g+"` + "`" + ` of value ` + "`" + `"+i+"` + "`" + ` "+("supplied to ` + "`" + `"+t+"` + "`" + `, expected an element type (a string ")+"or a ReactClass)."):null}M.__esModule=!0;var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(A){return typeof A}:function(A){return A&&"function"==typeof Symbol&&A.constructor===Symbol?"symbol":typeof A},i=t(1),T=I(i),E=t(182),N=I(E);M.default=(0,N.default)(g)},function(A,M){"use strict";function t(A){function M(M,t,I,g,e,i){var T=g||"<>",E=i||I;if(null==t[I])return M?new Error("Required "+e+" ` + "`" + `"+E+"` + "`" + ` was not specified "+("in ` + "`" + `"+T+"` + "`" + `.")):null;for(var N=arguments.length,o=Array(N>6?N-6:0),n=6;n=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return 0===A.button}function i(A){return!!(A.metaKey||A.altKey||A.ctrlKey||A.shiftKey)}function T(A){for(var M in A)if(Object.prototype.hasOwnProperty.call(A,M))return!1;return!0}function E(A,M){var t=M.query,I=M.hash,g=M.state;return t||I||g?{pathname:A,query:t,hash:I,state:g}:A}M.__esModule=!0;var N=Object.assign||function(A){for(var M=1;M=0;I--){var g=A[I],e=g.path||"";if(t=e.replace(/\/*$/,"/")+t,0===e.indexOf("/"))break}return"/"+t}},propTypes:{path:C,from:C,to:C.isRequired,query:c,state:c,onEnter:o.falsy,children:o.falsy},render:function(){(0,T.default)(!1)}});M.default=D,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}M.__esModule=!0;var g=t(1),e=I(g),i=t(8),T=I(i),E=t(30),N=t(34),o=e.default.PropTypes,n=o.string,C=o.func,c=e.default.createClass({displayName:"Route",statics:{createRouteFromReactElement:E.createRouteFromReactElement},propTypes:{path:n,component:N.component,components:N.components,getComponent:C,getComponents:C},render:function(){(0,T.default)(!1)}});M.default=c,A.exports=M.default},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A,M){var t={};for(var I in A)M.indexOf(I)>=0||Object.prototype.hasOwnProperty.call(A,I)&&(t[I]=A[I]);return t}function e(A){return!A||!A.__v2_compatible__}function i(A){return A&&A.getCurrentLocation}M.__esModule=!0;var T=Object.assign||function(A){for(var M=1;M=0&&0===window.sessionStorage.length)return;throw A}}function i(A){var M=void 0;try{M=window.sessionStorage.getItem(g(A))}catch(A){if(A.name===o)return null}if(M)try{return JSON.parse(M)}catch(A){}return null}M.__esModule=!0,M.saveState=e,M.readState=i;var T=t(23),E=(I(T),"@@History/"),N=["QuotaExceededError","QUOTA_EXCEEDED_ERR"],o="SecurityError"},function(A,M,t){"use strict";function I(A){return A&&A.__esModule?A:{default:A}}function g(A){function M(A){return E.canUseDOM?void 0:T.default(!1),t.listen(A)}var t=n.default(e({getUserConfirmation:N.getUserConfirmation},A,{go:N.go}));return e({},t,{listen:M})}M.__esModule=!0;var e=Object.assign||function(A){for(var M=1;M1&&(I=t[0]+"@",A=t[1]),A=A.replace(z,".");var g=A.split("."),e=T(g,M).join(".");return I+e}function N(A){for(var M,t,I=[],g=0,e=A.length;g=55296&&M<=56319&&g65535&&(A-=65536,M+=m(A>>>10&1023|55296),A=56320|1023&A),M+=m(A)}).join("")}function n(A){return A-48<10?A-22:A-65<26?A-65:A-97<26?A-97:j}function C(A,M){return A+22+75*(A<26)-((0!=M)<<5)}function c(A,M,t){var I=0;for(A=t?O(A/L):A>>1,A+=O(A/M);A>U*u>>1;I+=j)A=O(A/U);return O(I+(U+1)*A/(A+w))}function D(A){var M,t,I,g,e,T,E,N,C,D,a=[],B=A.length,Q=0,r=Y,s=l;for(t=A.lastIndexOf(d),t<0&&(t=0),I=0;I=128&&i("not-basic"),a.push(A.charCodeAt(I));for(g=t>0?t+1:0;g=B&&i("invalid-input"),N=n(A.charCodeAt(g++)),(N>=j||N>O((x-Q)/T))&&i("overflow"),Q+=N*T,C=E<=s?y:E>=s+u?u:E-s,!(NO(x/D)&&i("overflow"),T*=D;M=a.length+1,s=c(Q-e,M,0==e),O(Q/M)>x-r&&i("overflow"),r+=O(Q/M),Q%=M,a.splice(Q++,0,r)}return o(a)}function a(A){var M,t,I,g,e,T,E,o,n,D,a,B,Q,r,s,w=[];for(A=N(A),B=A.length,M=Y,t=0,e=l,T=0;T=M&&aO((x-t)/Q)&&i("overflow"),t+=(E-M)*Q,M=E,T=0;Tx&&i("overflow"),a==M){for(o=t,n=j;D=n<=e?y:n>=e+u?u:n-e,!(o= 0x80 (not a basic code point)","invalid-input":"Invalid input"},U=j-y,O=Math.floor,m=String.fromCharCode;s={version:"1.3.2",ucs2:{decode:N,encode:o},decode:D,encode:a,toASCII:Q,toUnicode:B},I=function(){return s}.call(M,t,M,A),!(void 0!==I&&(A.exports=I))}(this)}).call(M,t(128)(A),function(){return this}())},function(A,M){"use strict";A.exports={isString:function(A){return"string"==typeof A},isObject:function(A){return"object"==typeof A&&null!==A},isNull:function(A){return null===A},isNullOrUndefined:function(A){return null==A}}}]);`) -func productionIndex_bundle20170215t192644zJsBytes() ([]byte, error) { - return _productionIndex_bundle20170215t192644zJs, nil +func productionIndex_bundle20170215t224123zJsBytes() ([]byte, error) { + return _productionIndex_bundle20170215t224123zJs, nil } -func productionIndex_bundle20170215t192644zJs() (*asset, error) { - bytes, err := productionIndex_bundle20170215t192644zJsBytes() +func productionIndex_bundle20170215t224123zJs() (*asset, error) { + bytes, err := productionIndex_bundle20170215t224123zJsBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "production/index_bundle-2017-02-15T19-26-44Z.js", size: 2276742, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/index_bundle-2017-02-15T22-41-23Z.js", size: 2276858, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -370,7 +370,7 @@ func productionLoaderCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/loader.css", size: 1738, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -444,7 +444,7 @@ func productionLogoSvg() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/logo.svg", size: 3079, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -461,7 +461,7 @@ func productionSafariPng() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1487186821, 0)} + info := bindataFileInfo{name: "production/safari.png", size: 4971, mode: os.FileMode(436), modTime: time.Unix(1487198497, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -522,7 +522,7 @@ var _bindata = map[string]func() (*asset, error){ "production/favicon.ico": productionFaviconIco, "production/firefox.png": productionFirefoxPng, "production/index.html": productionIndexHTML, - "production/index_bundle-2017-02-15T19-26-44Z.js": productionIndex_bundle20170215t192644zJs, + "production/index_bundle-2017-02-15T22-41-23Z.js": productionIndex_bundle20170215t224123zJs, "production/loader.css": productionLoaderCss, "production/logo.svg": productionLogoSvg, "production/safari.png": productionSafariPng, @@ -574,7 +574,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "favicon.ico": {productionFaviconIco, map[string]*bintree{}}, "firefox.png": {productionFirefoxPng, map[string]*bintree{}}, "index.html": {productionIndexHTML, map[string]*bintree{}}, - "index_bundle-2017-02-15T19-26-44Z.js": {productionIndex_bundle20170215t192644zJs, map[string]*bintree{}}, + "index_bundle-2017-02-15T22-41-23Z.js": {productionIndex_bundle20170215t224123zJs, map[string]*bintree{}}, "loader.css": {productionLoaderCss, map[string]*bintree{}}, "logo.svg": {productionLogoSvg, map[string]*bintree{}}, "safari.png": {productionSafariPng, map[string]*bintree{}}, @@ -635,6 +635,6 @@ func assetFS() *assetfs.AssetFS { panic("unreachable") } -var UIReleaseTag = "RELEASE.2017-02-15T19-26-44Z" -var UICommitID = "7f86a21317f8369324ecc447a0a0bf01b60fac3e" -var UIVersion = "2017-02-15T19:26:44Z" +var UIReleaseTag = "RELEASE.2017-02-15T22-41-23Z" +var UICommitID = "b50e5164ba49acf3de57eb0dd5a45f1cd31b3411" +var UIVersion = "2017-02-15T22:41:23Z"