2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/ *  
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  MinIO  Cloud  Storage ,  ( C )  2015 - 2020  MinIO ,  Inc . 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  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 . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-19 07:23:42 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  cmd  
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2016-10-25 14:47:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"encoding/base64" 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"encoding/xml" 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											 
										 
										
											2016-02-04 08:46:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-12 05:26:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"path" 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-16 06:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"path/filepath" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 08:36:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strconv" 
							 
						 
					
						
							
								
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											 
										 
										
											2016-02-04 08:46:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-22 10:23:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/gorilla/mux" 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-12 03:02:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-15 00:38:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio-go/v7/pkg/set" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/minio/minio-go/v7/pkg/tags" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 08:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/cmd/config" 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-26 08:33:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/cmd/config/etcd/dns" 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-18 03:52:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/cmd/crypto" 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-03 13:34:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									xhttp  "github.com/minio/minio/cmd/http" 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/cmd/logger" 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-28 06:12:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectlock  "github.com/minio/minio/pkg/bucket/object/lock" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/bucket/policy" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 08:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/bucket/replication" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/env" 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:03:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/event" 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-03 05:40:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/handlers" 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/hash" 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 01:27:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									iampolicy  "github.com/minio/minio/pkg/iam/policy" 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/minio/minio/pkg/sync/errgroup" 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
									
										
										
										
											2020-07-22 08:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectLockConfig         =  "object-lock.xml" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucketTaggingConfig      =  "tagging.xml" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucketReplicationConfig  =  "replication.xml" 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Check if there are buckets on server without corresponding entry in etcd backend and
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// make entries. Here is the general flow
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// - Range over all the available buckets
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// - Check if a bucket has an entry in etcd backend
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -- If no, make an entry
  
						 
					
						
							
								
									
										
										
										
											2019-12-17 12:30:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// -- If yes, check if the entry matches local IP check if we
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    need to update the entry then proceed to update
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -- If yes, check if the IP of entry matches local IP.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    This means entry is for this instance.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -- If IP of the entry doesn't match, this means entry is
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    for another instance. Log an error to console.
  
						 
					
						
							
								
									
										
										
										
											2019-11-10 01:27:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  initFederatorBackend ( buckets  [ ] BucketInfo ,  objLayer  ObjectLayer )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( buckets )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Get buckets in the DNS
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dnsBuckets ,  err  :=  globalDNSConfig . List ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  &&  err  !=  dns . ErrNoEntriesFound  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-10 00:30:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( GlobalContext ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bucketsSet  :=  set . NewStringSet ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucketsToBeUpdated  :=  set . NewStringSet ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucketsInConflict  :=  set . NewStringSet ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  bucket  :=  range  buckets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bucketsSet . Add ( bucket . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r ,  ok  :=  dnsBuckets [ bucket . Name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bucketsToBeUpdated . Add ( bucket . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! globalDomainIPs . Intersection ( set . CreateStringSet ( getHostsSlice ( r ) ... ) ) . IsEmpty ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  globalDomainIPs . Difference ( set . CreateStringSet ( getHostsSlice ( r ) ... ) ) . IsEmpty ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// No difference in terms of domainIPs and nothing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// has changed so we don't change anything on the etcd.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// if domain IPs intersect then it won't be an empty set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// such an intersection means that bucket exists on etcd.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// but if we do see a difference with local domain IPs with
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// hostSlice from etcd then we should update with newer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// domainIPs, we proceed to do that here.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bucketsToBeUpdated . Add ( bucket . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// No IPs seem to intersect, this means that bucket exists but has
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// different IP addresses perhaps from a different deployment.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// bucket names are globally unique in federation at a given
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// path prefix, name collision is not allowed. We simply log
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// an error and continue.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bucketsInConflict . Add ( bucket . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Add/update buckets that are not registered with the DNS
 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-10 01:27:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									g  :=  errgroup . WithNErrs ( len ( buckets ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bucketsToBeUpdatedSlice  :=  bucketsToBeUpdated . ToSlice ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  index  :=  range  bucketsToBeUpdatedSlice  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-15 00:44:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										index  :=  index 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										g . Go ( func ( )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  globalDNSConfig . Put ( bucketsToBeUpdatedSlice [ index ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ,  index ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  err  :=  range  g . Wait ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-10 00:30:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											logger . LogIf ( GlobalContext ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  bucket  :=  range  bucketsInConflict . ToSlice ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-10 00:30:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( GlobalContext ,  fmt . Errorf ( "Unable to add bucket DNS entry for bucket %s, an entry exists for the same bucket. Use one of these IP addresses %v to access the bucket" ,  bucket ,  globalDomainIPs . ToSlice ( ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Remove buckets that are in DNS for this server, but aren't local
 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  bucket ,  records  :=  range  dnsBuckets  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  bucketsSet . Contains ( bucket )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  globalDomainIPs . Intersection ( set . CreateStringSet ( getHostsSlice ( records ) ... ) ) . IsEmpty ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// This is not for our server, so we can continue
 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 23:49:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// We go to here, so we know the bucket no longer exists,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// but is registered in DNS to this server
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  =  globalDNSConfig . Delete ( bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-10 00:30:02 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											logger . LogIf ( GlobalContext ,  fmt . Errorf ( "Failed to remove DNS entry for %s due to %w" , 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												bucket ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-05 23:18:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-12-27 15:38:38 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// GetBucketLocationHandler - GET Bucket location.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// -------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This operation returns bucket location.
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  GetBucketLocationHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "GetBucketLocation" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "GetBucketLocation" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-27 15:38:38 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . GetBucketLocationAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-22 05:51:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-29 05:14:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									getBucketInfo  :=  objectAPI . GetBucketInfo 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 08:09:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-29 05:14:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  _ ,  err  :=  getBucketInfo ( ctx ,  bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-20 09:49:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-27 15:38:38 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Generate response.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-07 04:16:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									encodedSuccessResponse  :=  encodeResponse ( LocationResponse { } ) 
							 
						 
					
						
							
								
									
										
											 
										
											
												config/main: Re-write config files - add to new config v3
- New config format.
```
{
	"version": "3",
	"address": ":9000",
    "backend": {
          "type": "fs",
          "disk": "/path"
    },
	"credential": {
		"accessKey": "WLGDGYAQYIGI833EV05A",
		"secretKey": "BYvgJM101sHngl2uzjXS/OBF/aMxAN06JrJ3qJlF"
	},
	"region": "us-east-1",
	"logger": {
		"file": {
			"enable": false,
			"fileName": "",
			"level": "error"
		},
		"syslog": {
			"enable": false,
			"address": "",
			"level": "debug"
		},
		"console": {
			"enable": true,
			"level": "fatal"
		}
	}
}
```
New command lines in lieu of supporting XL.
Minio initialize filesystem backend.
~~~
$ minio init fs <path>
~~~
Minio initialize XL backend.
~~~
$ minio init xl <url1>...<url16>
~~~
For 'fs' backend it starts the server.
~~~
$ minio server
~~~
For 'xl' backend it waits for servers to join.
~~~
$ minio server
... [PROGRESS BAR] of servers connecting
~~~
Now on other servers execute 'join' and they connect.
~~~
....
minio join <url1> -- from <url2> && minio server
minio join <url1> -- from <url3> && minio server
...
...
minio join <url1> -- from <url16> && minio server
~~~
											 
										 
										
											2016-02-13 07:27:10 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Get current region.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-23 13:59:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									region  :=  globalServerRegion 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-19 04:24:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  region  !=  globalMinioDefaultRegion  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-07 04:16:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										encodedSuccessResponse  =  encodeResponse ( LocationResponse { 
							 
						 
					
						
							
								
									
										
											 
										
											
												config/main: Re-write config files - add to new config v3
- New config format.
```
{
	"version": "3",
	"address": ":9000",
    "backend": {
          "type": "fs",
          "disk": "/path"
    },
	"credential": {
		"accessKey": "WLGDGYAQYIGI833EV05A",
		"secretKey": "BYvgJM101sHngl2uzjXS/OBF/aMxAN06JrJ3qJlF"
	},
	"region": "us-east-1",
	"logger": {
		"file": {
			"enable": false,
			"fileName": "",
			"level": "error"
		},
		"syslog": {
			"enable": false,
			"address": "",
			"level": "debug"
		},
		"console": {
			"enable": true,
			"level": "fatal"
		}
	}
}
```
New command lines in lieu of supporting XL.
Minio initialize filesystem backend.
~~~
$ minio init fs <path>
~~~
Minio initialize XL backend.
~~~
$ minio init xl <url1>...<url16>
~~~
For 'fs' backend it starts the server.
~~~
$ minio server
~~~
For 'xl' backend it waits for servers to join.
~~~
$ minio server
... [PROGRESS BAR] of servers connecting
~~~
Now on other servers execute 'join' and they connect.
~~~
....
minio join <url1> -- from <url2> && minio server
minio join <url1> -- from <url3> && minio server
...
...
minio join <url1> -- from <url16> && minio server
~~~
											 
										 
										
											2016-02-13 07:27:10 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											Location :  region , 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  encodedSuccessResponse ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-12-27 15:38:38 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 11:15:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// ListMultipartUploadsHandler - GET Bucket (List Multipart uploads)
  
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// -------------------------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This operation lists in-progress multipart uploads. An in-progress
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// multipart upload is a multipart upload that has been initiated,
  
						 
					
						
							
								
									
										
										
										
											2015-10-17 10:09:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// using the Initiate Multipart Upload request, but has not yet been
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// completed or aborted. This operation returns at most 1,000 multipart
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// uploads in the response.
  
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  ListMultipartUploadsHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "ListMultipartUploads" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "ListMultipartUploads" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-17 10:09:35 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . ListBucketMultipartUploadsAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-24 14:14:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									prefix ,  keyMarker ,  uploadIDMarker ,  delimiter ,  maxUploads ,  encodingType ,  errCode  :=  getBucketMultipartResources ( r . URL . Query ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  errCode  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( errCode ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-18 22:31:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												objectAPI: Fix object API interface, remove unnecessary structs.
ObjectAPI changes.
```
ListObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, *probe.Error)
ListMultipartUploads(bucket, objectPrefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (ListMultipartsInfo, *probe.Error)
ListObjectParts(bucket, object, uploadID string, partNumberMarker, maxParts int) (ListPartsInfo, *probe.Error)
CompleteMultipartUpload(bucket string, object string, uploadID string, parts []completePart) (ObjectInfo, *probe.Error)
```
											 
										 
										
											2016-04-03 16:34:20 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  maxUploads  <  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrInvalidMaxUploads ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-17 08:22:45 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-06 03:26:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  keyMarker  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-30 05:24:10 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// Marker not common with prefix is not implemented.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-06 15:16:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ! HasPrefix ( keyMarker ,  prefix )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrNotImplemented ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-30 05:24:10 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-06 03:26:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									listMultipartsInfo ,  err  :=  objectAPI . ListMultipartUploads ( ctx ,  bucket ,  prefix ,  keyMarker ,  uploadIDMarker ,  delimiter ,  maxUploads ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-19 18:20:07 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-04 07:17:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-19 18:20:07 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// generate response
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-24 14:14:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									response  :=  generateListMultipartUploadsResponse ( bucket ,  listMultipartsInfo ,  encodingType ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-07 04:16:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									encodedSuccessResponse  :=  encodeResponse ( response ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-01-08 16:40:06 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// write success response.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  encodedSuccessResponse ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-10 00:21:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// ListBucketsHandler - GET Service.
  
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// -----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This implementation of the GET operation returns a list of all buckets
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// owned by the authenticated sender of the request.
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  ListBucketsHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "ListBuckets" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "ListBuckets" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									listBuckets  :=  objectAPI . ListBuckets 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 01:27:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									accessKey ,  owner ,  s3Error  :=  checkRequestAuthTypeToAccessKey ( ctx ,  r ,  policy . ListAllMyBucketsAction ,  "" ,  "" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-03 03:35:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  !=  ErrNone  &&  s3Error  !=  ErrAccessDenied  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If etcd, dns federation configured list buckets from etcd.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  bucketsInfo  [ ] BucketInfo 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-30 00:56:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  globalDNSConfig  !=  nil  &&  globalBucketFederation  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dnsBuckets ,  err  :=  globalDNSConfig . List ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-13 05:12:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  &&  err  !=  dns . ErrNoEntriesFound  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  _ ,  dnsRecords  :=  range  dnsBuckets  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											bucketsInfo  =  append ( bucketsInfo ,  BucketInfo { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-03 16:24:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												Name :     dnsRecords [ 0 ] . Key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Created :  dnsRecords [ 0 ] . CreationDate , 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Invoke the list buckets.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bucketsInfo ,  err  =  listBuckets ( ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-04 07:17:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-18 04:23:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-03 03:35:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  ==  ErrAccessDenied  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Set prefix value for "s3:prefix" policy conditionals.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r . Header . Set ( "prefix" ,  "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Set delimiter value for "s3:delimiter" policy conditionals.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r . Header . Set ( "delimiter" ,  SlashSeparator ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// err will be nil here as we already called this function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// earlier in this request.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-15 02:28:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										claims ,  _  :=  getClaimsFromToken ( r ,  getSessionToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-03 03:35:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										n  :=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Use the following trick to filter in place
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// https://github.com/golang/go/wiki/SliceTricks#filter-in-place
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  bucketInfo  :=  range  bucketsInfo  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  globalIAMSys . IsAllowed ( iampolicy . Args { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												AccountName :      accessKey , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Action :           iampolicy . ListBucketAction , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												BucketName :       bucketInfo . Name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ConditionValues :  getConditionValues ( r ,  "" ,  accessKey ,  claims ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												IsOwner :          owner , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ObjectName :       "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Claims :           claims , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bucketsInfo [ n ]  =  bucketInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												n ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bucketsInfo  =  bucketsInfo [ : n ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// No buckets can be filtered return access denied error.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( bucketsInfo )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-13 01:27:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-18 04:23:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Generate response.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-03 03:35:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									response  :=  generateListBucketsResponse ( bucketsInfo ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-18 04:23:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									encodedSuccessResponse  :=  encodeResponse ( response ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-18 04:23:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Write response.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  encodedSuccessResponse ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// DeleteMultipleObjectsHandler - deletes multiple objects.
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  DeleteMultipleObjectsHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "DeleteMultipleObjects" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "DeleteMultipleObjects" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-03 09:40:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-23 11:36:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Content-Md5 is requied should be set
 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-23 11:36:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  _ ,  ok  :=  r . Header [ xhttp . ContentMD5 ] ;  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMissingContentMD5 ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-23 11:36:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Content-Length is required and should be non-zero
 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-23 11:36:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  r . ContentLength  <=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMissingContentLength ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-21 13:59:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// The max. XML contains 100000 object names (each at most 1024 bytes long) + XML overhead
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  maxBodySize  =  2  *  100000  *  1024 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Unmarshal list of keys to be deleted.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									deleteObjects  :=  & DeleteObjectsRequest { } 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-21 13:59:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  xmlDecoder ( r . Body ,  deleteObjects ,  maxBodySize ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-12 09:50:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ,  logger . Application ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-23 11:36:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-28 07:44:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-10 23:30:23 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Before proceeding validate if bucket exists.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_ ,  err  :=  objectAPI . GetBucketInfo ( ctx ,  bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-14 03:25:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									deleteObjectsFn  :=  objectAPI . DeleteObjects 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-21 12:21:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  api . CacheAPI ( )  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-14 03:25:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										deleteObjectsFn  =  api . CacheAPI ( ) . DeleteObjects 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-21 12:21:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-02 16:59:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  objectsToDelete  =  map [ ObjectToDelete ] int { } 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 05:18:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									getObjectInfoFn  :=  objectAPI . GetObjectInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  api . CacheAPI ( )  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										getObjectInfoFn  =  api . CacheAPI ( ) . GetObjectInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dErrs  :=  make ( [ ] DeleteError ,  len ( deleteObjects . Objects ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-02 16:59:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  index ,  object  :=  range  deleteObjects . Objects  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  apiErrCode  :=  checkRequestAuthType ( ctx ,  r ,  policy . DeleteObjectAction ,  bucket ,  object . ObjectName ) ;  apiErrCode  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  apiErrCode  ==  ErrSignatureDoesNotMatch  ||  apiErrCode  ==  ErrInvalidAccessKeyID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( apiErrCode ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-22 22:54:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
									
										
										
										
											2017-08-16 03:49:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											apiErr  :=  errorCodes . ToAPIErr ( apiErrCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dErrs [ index ]  =  DeleteError { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Code :       apiErr . Code , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Message :    apiErr . Description , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Key :        object . ObjectName , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												VersionID :  object . VersionID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-21 12:21:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 04:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  object . VersionID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  rcfg ,  _  :=  globalBucketObjectLockSys . Get ( bucket ) ;  rcfg . LockEnabled  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  apiErrCode  :=  enforceRetentionBypassForDelete ( ctx ,  r ,  bucket ,  object ,  getObjectInfoFn ) ;  apiErrCode  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													apiErr  :=  errorCodes . ToAPIErr ( apiErrCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													dErrs [ index ]  =  DeleteError { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														Code :       apiErr . Code , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														Message :    apiErr . Description , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														Key :        object . ObjectName , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														VersionID :  object . VersionID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 04:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 05:18:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 04:44:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Avoid duplicate objects, we use map to filter them out.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  _ ,  ok  :=  objectsToDelete [ object ] ;  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											objectsToDelete [ object ]  =  index 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-20 09:42:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-14 03:25:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									toNames  :=  func ( input  map [ ObjectToDelete ] int )  ( output  [ ] ObjectToDelete )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										output  =  make ( [ ] ObjectToDelete ,  len ( input ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 09:51:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										idx  :=  0 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  obj  :=  range  input  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											output [ idx ]  =  obj 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 09:51:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											idx ++ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-22 22:54:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-14 03:25:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 09:51:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									deleteList  :=  toNames ( objectsToDelete ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dObjects ,  errs  :=  deleteObjectsFn ( ctx ,  bucket ,  deleteList ,  ObjectOptions { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Versioned :  globalBucketVersioningSys . Enabled ( bucket ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-14 03:25:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									deletedObjects  :=  make ( [ ] DeletedObject ,  len ( deleteObjects . Objects ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  range  errs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dindex  :=  objectsToDelete [ deleteList [ i ] ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										apiErr  :=  toAPIError ( ctx ,  errs [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  apiErr . Code  ==  ""  ||  apiErr . Code  ==  "NoSuchKey"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											deletedObjects [ dindex ]  =  dObjects [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dErrs [ dindex ]  =  DeleteError { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Code :       apiErr . Code , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Message :    apiErr . Description , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Key :        deleteList [ i ] . ObjectName , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											VersionID :  deleteList [ i ] . VersionID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-02 16:59:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  deleteErrors  [ ] DeleteError 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  _ ,  dErr  :=  range  dErrs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  dErr . Code  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											deleteErrors  =  append ( deleteErrors ,  dErr ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-08 02:49:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-02 16:59:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Generate response
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									response  :=  generateMultiDeleteResponse ( deleteObjects . Quiet ,  deletedObjects ,  deleteErrors ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									encodedSuccessResponse  :=  encodeResponse ( response ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  encodedSuccessResponse ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-02 16:59:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-09-29 13:46:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Notify deleted event for objects.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  dobj  :=  range  deletedObjects  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										objInfo  :=  ObjectInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Name :       dobj . ObjectName , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											VersionID :  dobj . VersionID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  dobj . DeleteMarker  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											objInfo  =  ObjectInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Name :          dobj . ObjectName , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												DeleteMarker :  dobj . DeleteMarker , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												VersionID :     dobj . DeleteMarkerVersionID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:03:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sendEvent ( eventArgs { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											EventName :     event . ObjectRemovedDelete , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BucketName :    bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Object :        objInfo , 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-03 09:40:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ReqParams :     extractReqParams ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											RespElements :  extractRespElements ( w ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											UserAgent :     r . UserAgent ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 02:45:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											Host :          handlers . GetSourceIP ( r ) , 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-29 13:46:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-02 16:59:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-06 08:43:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 11:15:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// PutBucketHandler - PUT Bucket
  
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This implementation of the PUT operation creates a new bucket for authenticated request
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  PutBucketHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "PutBucket" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "PutBucket" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectLockEnabled  :=  false 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-14 07:51:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  vs ,  found  :=  r . Header [ http . CanonicalHeaderKey ( "x-amz-bucket-object-lock-enabled" ) ] ;  found  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										v  :=  strings . ToLower ( strings . Join ( vs ,  "" ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  v  !=  "true"  &&  v  !=  "false"  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrInvalidRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-14 07:51:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										objectLockEnabled  =  v  ==  "true" 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . CreateBucketAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-15 00:17:30 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 05:50:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Parse incoming location constraint.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									location ,  s3Error  :=  parseLocationConstraint ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-26 11:00:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-21 08:35:38 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-24 13:51:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 05:50:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Validate if location sent by the client is valid, reject
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// requests which do not follow valid region requirements.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! isValidLocation ( location )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrInvalidRegion ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-04 05:50:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									opts  :=  BucketOptions { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Location :     location , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										LockEnabled :  objectLockEnabled , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  globalDNSConfig  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-23 00:25:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sr ,  err  :=  globalDNSConfig . Get ( bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-13 05:12:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  ==  dns . ErrNoEntriesFound  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// Proceed to creating a bucket.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  err  =  objectAPI . MakeBucketWithLocation ( ctx ,  bucket ,  opts ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-02 00:53:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  err  =  globalDNSConfig . Put ( bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-28 12:52:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													objectAPI . DeleteBucket ( ctx ,  bucket ,  false ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-22 02:03:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// Load updated bucket metadata into memory.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												globalNotificationSys . LoadBucketMetadata ( GlobalContext ,  bucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												// Make sure to add Location information here only for bucket
 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-03 13:34:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												w . Header ( ) . Set ( xhttp . Location , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													getObjectLocation ( r ,  globalDomainNames ,  bucket ,  "" ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-21 03:52:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												sendEvent ( eventArgs { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													EventName :     event . BucketCreated , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													BucketName :    bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ReqParams :     extractReqParams ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													RespElements :  extractRespElements ( w ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													UserAgent :     r . UserAgent ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													Host :          handlers . GetSourceIP ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-23 00:25:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiErr  :=  ErrBucketAlreadyExists 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! globalDomainIPs . Intersection ( set . CreateStringSet ( getHostsSlice ( sr ) ... ) ) . IsEmpty ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											apiErr  =  ErrBucketAlreadyOwnedByYou 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// No IPs seem to intersect, this means that bucket exists but has
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// different IP addresses perhaps from a different deployment.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// bucket names are globally unique in federation at a given
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// path prefix, name collision is not allowed. Return appropriate error.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( apiErr ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-16 09:45:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-24 13:51:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Proceed to creating a bucket.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  :=  objectAPI . MakeBucketWithLocation ( ctx ,  bucket ,  opts ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-09-19 18:20:07 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-04 07:17:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-22 02:03:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Load updated bucket metadata into memory.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									globalNotificationSys . LoadBucketMetadata ( GlobalContext ,  bucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-09-19 18:20:07 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Make sure to add Location information here only for bucket
 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-03 13:34:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									w . Header ( ) . Set ( xhttp . Location ,  path . Clean ( r . URL . Path ) )  // Clean any trailing slashes.
 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-21 03:52:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sendEvent ( eventArgs { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										EventName :     event . BucketCreated , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BucketName :    bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ReqParams :     extractReqParams ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RespElements :  extractRespElements ( w ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										UserAgent :     r . UserAgent ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Host :          handlers . GetSourceIP ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// PostPolicyBucketHandler - POST policy
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This implementation of the POST operation handles object creation with a specified
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// signature policy in multipart/form-data
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  PostPolicyBucketHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "PostPolicyBucket" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "PostPolicyBucket" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-15 13:39:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  crypto . S3KMS . IsRequested ( r . Header )  {  // SSE-KMS is not supported
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrNotImplemented ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-15 13:39:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-21 05:56:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! api . EncryptionEnabled ( )  &&  crypto . IsRequested ( r . Header )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrNotImplemented ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-15 13:39:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-14 08:30:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									bucket  :=  mux . Vars ( r ) [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-06-29 13:09:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// To detect if the client has disconnected.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-05 05:33:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									r . Body  =  & contextReader { r . Body ,  r . Context ( ) } 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-29 13:09:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Require Content-Length to be set in the request
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									size  :=  r . ContentLength 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  size  <  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMissingContentLength ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-23 11:18:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									resource ,  err  :=  getResource ( r . URL . Path ,  r . Host ,  globalDomainNames ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-16 06:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrInvalidRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-16 06:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Make sure that the URL  does not contain object name.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  bucket  !=  filepath . Clean ( resource [ 1 : ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMethodNotAllowed ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-16 06:10:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Here the parameter is the size of the form data that should
 
							 
						 
					
						
							
								
									
										
										
										
											2016-03-23 08:54:31 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// be loaded in memory, the remaining being put in temporary files.
 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-30 05:24:10 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									reader ,  err  :=  r . MultipartReader ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMalformedPOSTRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Read multipart data and save in memory and in the disk if needed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									form ,  err  :=  reader . ReadForm ( maxFormMemory ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-12 09:50:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ,  logger . Application ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMalformedPOSTRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-10 13:18:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Remove all tmp files created during multipart upload
 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  form . RemoveAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Extract all form fields
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fileBody ,  fileName ,  fileSize ,  formValues ,  err  :=  extractPostPolicyFormValues ( ctx ,  form ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-12 09:50:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ,  logger . Application ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMalformedPOSTRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-10 04:37:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check if file is provided, error out otherwise.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  fileBody  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrPOSTFileRequired ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-10 04:37:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Close multipart file
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  fileBody . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									formValues . Set ( "Bucket" ,  bucket ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  fileName  !=  ""  &&  strings . Contains ( formValues . Get ( "Key" ) ,  "${filename}" )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-28 08:51:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										// S3 feature to replace ${filename} found in Key form field
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// by the filename attribute passed in multipart
 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										formValues . Set ( "Key" ,  strings . Replace ( formValues . Get ( "Key" ) ,  "${filename}" ,  fileName ,  - 1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									object  :=  formValues . Get ( "Key" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									successRedirect  :=  formValues . Get ( "success_action_redirect" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									successStatus  :=  formValues . Get ( "success_action_status" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  redirectURL  * url . URL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  successRedirect  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										redirectURL ,  err  =  url . Parse ( successRedirect ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMalformedPOSTRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-28 08:51:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Verify policy signature.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									errCode  :=  doesPolicySignatureMatch ( formValues ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errCode  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( errCode ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-25 14:47:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									policyBytes ,  err  :=  base64 . StdEncoding . DecodeString ( formValues . Get ( "Policy" ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-25 14:47:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMalformedPOSTRequest ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-25 14:47:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-04 04:01:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Handle policy if it is set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( policyBytes )  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-23 05:20:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-04 04:01:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										postPolicyForm ,  err  :=  parsePostPolicyForm ( string ( policyBytes ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-23 05:20:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrPostPolicyConditionInvalidFormat ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-21 20:15:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-04 04:01:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// Make sure formValues adhere to policy restrictions.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-06 04:10:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  =  checkPostPolicy ( formValues ,  postPolicyForm ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-24 13:06:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErrWithErr ( ErrAccessDenied ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-03 02:45:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-21 20:15:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-04 04:01:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// 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  fileSize  <  lengthRange . Min  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  errDataTooSmall ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-04 04:01:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  fileSize  >  lengthRange . Max  ||  isMaxObjectSize ( fileSize )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  errDataTooLarge ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-04 04:01:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-25 14:47:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-12-20 08:14:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Extract metadata to be saved from received Form.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-11 11:27:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									metadata  :=  make ( map [ string ] string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  =  extractMetadataFromMap ( ctx ,  formValues ,  metadata ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-06 07:56:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-06 07:56:10 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-03 06:51:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-09 09:35:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									hashReader ,  err  :=  hash . NewReader ( fileBody ,  fileSize ,  "" ,  "" ,  fileSize ,  globalCLIContext . StrictS3Compat ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-06 06:04:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										logger . LogIf ( ctx ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-22 13:30:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-15 09:36:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									rawReader  :=  hashReader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pReader  :=  NewPutObjReader ( rawReader ,  nil ,  nil ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-10 08:01:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  objectEncryptionKey  crypto . ObjectKey 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-15 05:35:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 17:42:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check if bucket encryption is enabled
 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  _ ,  err  =  globalBucketSSEConfigSys . Get ( bucket ) ;  err  ==  nil  ||  globalAutoEncryption  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This request header needs to be set prior to setting ObjectOptions
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! crypto . SSEC . IsRequested ( r . Header )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											r . Header . Add ( crypto . SSEHeader ,  crypto . SSEAlgorithmAES256 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-15 05:35:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-06 06:16:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// get gateway encryption options
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  opts  ObjectOptions 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-09 13:31:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									opts ,  err  =  putOpts ( ctx ,  r ,  bucket ,  object ,  metadata ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-06 06:16:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponseHeadersOnly ( w ,  toAPIError ( ctx ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-06 06:16:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  objectAPI . IsEncryptionSupported ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-06 15:16:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  crypto . IsRequested ( formValues )  &&  ! HasSuffix ( object ,  SlashSeparator )  {  // handle SSE requests
 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-21 05:56:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  crypto . SSECopy . IsRequested ( r . Header )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  errInvalidEncryptionParameters ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											var  reader  io . Reader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											var  key  [ ] byte 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-18 03:52:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  crypto . SSEC . IsRequested ( formValues )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												key ,  err  =  ParseSSECustomerHeader ( formValues ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-18 03:52:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-15 09:36:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											reader ,  objectEncryptionKey ,  err  =  newEncryptReader ( hashReader ,  key ,  bucket ,  object ,  metadata ,  crypto . S3 . IsRequested ( formValues ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											info  :=  ObjectInfo { Size :  fileSize } 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-09 09:35:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// do not try to verify encrypted content
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											hashReader ,  err  =  hash . NewReader ( reader ,  info . EncryptedSize ( ) ,  "" ,  "" ,  fileSize ,  globalCLIContext . StrictS3Compat ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-10 08:01:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											pReader  =  NewPutObjReader ( rawReader ,  hashReader ,  & objectEncryptionKey ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-06 00:02:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-09 13:31:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objInfo ,  err  :=  objectAPI . PutObject ( ctx ,  bucket ,  object ,  pReader ,  opts ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// We must not use the http.Header().Set method here because some (broken)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// clients expect the ETag header key to be literally "ETag" - not "Etag" (case-sensitive).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Therefore, we have to set the ETag directly as map entry.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-03 13:34:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									w . Header ( ) [ xhttp . ETag ]  =  [ ] string { ` " `  +  objInfo . ETag  +  ` " ` } 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Set the relevant version ID as part of the response header.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objInfo . VersionID  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										w . Header ( ) [ xhttp . AmzVersionID ]  =  [ ] string { objInfo . VersionID } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									w . Header ( ) . Set ( xhttp . Location ,  getObjectLocation ( r ,  globalDomainNames ,  bucket ,  object ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-05 13:01:58 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Notify object created event.
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-16 04:03:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  sendEvent ( eventArgs { 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-03 09:40:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										EventName :     event . ObjectCreatedPost , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BucketName :    objInfo . Bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Object :        objInfo , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ReqParams :     extractReqParams ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RespElements :  extractRespElements ( w ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										UserAgent :     r . UserAgent ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 02:45:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										Host :          handlers . GetSourceIP ( r ) , 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  successRedirect  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Replace raw query params..
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										redirectURL . RawQuery  =  getRedirectPostRawQuery ( objInfo ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeRedirectSeeOther ( w ,  redirectURL . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-07-24 13:51:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Decide what http response to send depending on success_action_status parameter
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  successStatus  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  "201" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										resp  :=  encodeResponse ( PostResponse { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Bucket :    objInfo . Bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Key :       objInfo . Name , 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-15 03:05:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ETag :      ` " `  +  objInfo . ETag  +  ` " ` , 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											Location :  w . Header ( ) . Get ( xhttp . Location ) , 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeResponse ( w ,  http . StatusCreated ,  resp ,  mimeXML ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-14 05:41:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									case  "200" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-19 05:39:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeSuccessNoContent ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-02 14:51:17 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 11:15:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// HeadBucketHandler - HEAD Bucket
  
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// This operation is useful to determine if a bucket exists.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The operation returns a 200 OK if the bucket exists and you
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// have permission to access it. Otherwise, the operation might
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// return responses such as 404 Not Found and 403 Forbidden.
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  HeadBucketHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "HeadBucket" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "HeadBucket" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-02-16 09:42:39 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-03 11:31:22 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponseHeadersOnly ( w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2016-11-22 05:51:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . ListBucketAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponseHeadersOnly ( w ,  errorCodes . ToAPIErr ( s3Error ) ) 
							 
						 
					
						
							
								
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											 
										 
										
											2016-02-04 08:46:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-29 05:14:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									getBucketInfo  :=  objectAPI . GetBucketInfo 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 08:09:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-29 05:14:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  _ ,  err  :=  getBucketInfo ( ctx ,  bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-12 17:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponseHeadersOnly ( w ,  toAPIError ( ctx ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-08-04 07:17:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-01-06 16:37:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-01 05:42:29 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2015-10-17 02:26:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// DeleteBucketHandler - Delete bucket
  
						 
					
						
							
								
									
										
										
										
											2016-04-13 03:45:15 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  DeleteBucketHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
									
										
										
										
											2018-07-21 09:46:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "DeleteBucket" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-15 03:01:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-22 12:03:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "DeleteBucket" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-13 03:25:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-25 06:53:30 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 08:51:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 08:36:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Verify if the caller has sufficient permissions.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . DeleteBucketAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-28 12:52:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									forceDelete  :=  false 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 08:51:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  value  :=  r . Header . Get ( xhttp . MinIOForceDelete ) ;  value  !=  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 08:36:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										forceDelete ,  err  =  strconv . ParseBool ( value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											apiErr  :=  errorCodes . ToAPIErr ( ErrInvalidRequest ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											apiErr . Description  =  err . Error ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  apiErr ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-28 12:52:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 08:36:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// if force delete header is set, we need to evaluate the policy anyways
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// regardless of it being true or not.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 08:51:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . ForceDeleteBucketAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-11 09:47:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 08:36:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  forceDelete  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  rcfg ,  _  :=  globalBucketObjectLockSys . Get ( bucket ) ;  rcfg . LockEnabled  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrMethodNotAllowed ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2016-02-05 04:52:25 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-29 05:14:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									deleteBucket  :=  objectAPI . DeleteBucket 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-10 08:09:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-07-24 13:51:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Attempt to delete bucket.
 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-28 12:52:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  deleteBucket ( ctx ,  bucket ,  forceDelete ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  _ ,  ok  :=  err . ( BucketNotEmpty ) ;  ok  &&  ( globalBucketVersioningSys . Enabled ( bucket )  ||  globalBucketVersioningSys . Suspended ( bucket ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											apiErr  :=  toAPIError ( ctx ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											apiErr . Description  =  "The bucket you tried to delete is not empty. You must delete all versions in the bucket." 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  apiErr ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-17 02:26:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											 
										 
										
											2016-02-04 08:46:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									globalNotificationSys . DeleteBucketMetadata ( ctx ,  bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  globalDNSConfig  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  globalDNSConfig . Delete ( bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 11:04:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											logger . LogIf ( ctx ,  fmt . Errorf ( "Unable to delete bucket DNS entry %w, please delete it manually using etcdctl" ,  err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-14 08:07:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-03 10:18:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											 
										 
										
											2016-02-04 08:46:56 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-17 11:02:37 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									writeSuccessNoContent ( w ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-21 03:52:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sendEvent ( eventArgs { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										EventName :     event . BucketRemoved , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BucketName :    bucket , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ReqParams :     extractReqParams ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RespElements :  extractRespElements ( w ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										UserAgent :     r . UserAgent ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Host :          handlers . GetSourceIP ( r ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-10-17 02:26:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PutBucketObjectLockConfigHandler - PUT Bucket object lock configuration.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Places an Object Lock configuration on the specified bucket. The rule
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// specified in the Object Lock configuration will be applied by default
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// to every new object placed in the specified bucket.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  PutBucketObjectLockConfigHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "PutBucketObjectLockConfig" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "PutBucketObjectLockConfig" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-23 08:39:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! globalIsErasure  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponseJSON ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrNotImplemented ) ,  r . URL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 05:18:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . PutBucketObjectLockConfigurationAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-17 07:41:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									config ,  err  :=  objectlock . ParseObjectLockConfig ( r . Body ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-14 00:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiErr  :=  errorCodes . ToAPIErr ( ErrMalformedXML ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										apiErr . Description  =  err . Error ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  apiErr ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-02 00:53:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									configData ,  err  :=  xml . Marshal ( config ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-02 00:53:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-02 00:53:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-24 01:01:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Deny object locking configuration settings on existing buckets without object lock enabled.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  err  =  globalBucketMetadataSys . GetObjectLockConfig ( bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  globalBucketMetadataSys . Update ( bucket ,  objectLockConfig ,  configData ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBucketObjectLockConfigHandler - GET Bucket object lock configuration.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Gets the Object Lock configuration for a bucket. The rule specified in
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// the Object Lock configuration will be applied by default to every new
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// object placed in the specified bucket.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  GetBucketObjectLockConfigHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "GetBucketObjectLockConfig" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "GetBucketObjectLockConfig" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-11-21 05:18:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// check if user has permissions to perform this operation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . GetBucketObjectLockConfigurationAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-02 00:53:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-21 01:18:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									config ,  err  :=  globalBucketMetadataSys . GetObjectLockConfig ( bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									configData ,  err  :=  xml . Marshal ( config ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-13 06:50:18 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  configData ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2020-05-06 05:18:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PutBucketTaggingHandler - PUT Bucket tagging.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  PutBucketTaggingHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "PutBucketTagging" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "PutBucketTagging" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . PutBucketTaggingAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-06 05:18:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tags ,  err  :=  tags . ParseBucketXML ( io . LimitReader ( r . Body ,  r . ContentLength ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										apiErr  :=  errorCodes . ToAPIErr ( ErrMalformedXML ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										apiErr . Description  =  err . Error ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  apiErr ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-20 04:53:54 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									configData ,  err  :=  xml . Marshal ( tags ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-16 13:09:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  =  globalBucketMetadataSys . Update ( bucket ,  bucketTaggingConfig ,  configData ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-06 05:18:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBucketTaggingHandler - GET Bucket tagging.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  GetBucketTaggingHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "GetBucketTagging" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "GetBucketTagging" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-06 05:18:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// check if user has permissions to perform this operation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . GetBucketTaggingAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-21 01:18:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									config ,  err  :=  globalBucketMetadataSys . GetTaggingConfig ( bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									configData ,  err  :=  xml . Marshal ( config ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-09 04:44:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-06 05:18:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  configData ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// DeleteBucketTaggingHandler - DELETE Bucket tagging.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  DeleteBucketTaggingHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "DeleteBucketTagging" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "DeleteBucketTagging" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . PutBucketTaggingAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-16 13:09:39 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  globalBucketMetadataSys . Update ( bucket ,  bucketTaggingConfig ,  nil ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-06 05:18:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2020-07-22 08:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// PutBucketReplicationConfigHandler - PUT Bucket replication configuration.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Add a replication configuration on the specified bucket as specified in https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  PutBucketReplicationConfigHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "PutBucketReplicationConfig" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "PutBucketReplicationConfig" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-23 08:39:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! globalIsErasure  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponseJSON ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrNotImplemented ) ,  r . URL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 08:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Turn off replication if disk crawl is unavailable.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  env . Get ( envDataUsageCrawlConf ,  config . EnableOn )  ==  config . EnableOff  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponseJSON ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrBucketReplicationDisabledError ) ,  r . URL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . PutReplicationConfigurationAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check if bucket exists.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  err  :=  objectAPI . GetBucketInfo ( ctx ,  bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  versioned  :=  globalBucketVersioningSys . Enabled ( bucket ) ;  ! versioned  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrReplicationNeedsVersioningError ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									replicationConfig ,  err  :=  replication . ParseConfig ( io . LimitReader ( r . Body ,  r . ContentLength ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										apiErr  :=  errorCodes . ToAPIErr ( ErrMalformedXML ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										apiErr . Description  =  err . Error ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  apiErr ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-31 10:55:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sameTarget ,  err  :=  validateReplicationDestination ( ctx ,  bucket ,  replicationConfig ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 08:49:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Validate the received bucket replication config
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  replicationConfig . Validate ( bucket ,  sameTarget ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									configData ,  err  :=  xml . Marshal ( replicationConfig ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  =  globalBucketMetadataSys . Update ( bucket ,  bucketReplicationConfig ,  configData ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GetBucketReplicationConfigHandler - GET Bucket replication configuration.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Gets the replication configuration for a bucket.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  GetBucketReplicationConfigHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "GetBucketReplicationConfig" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "GetBucketReplicationConfig" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check if user has permissions to perform this operation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . GetReplicationConfigurationAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check if bucket exists.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  err  :=  objectAPI . GetBucketInfo ( ctx ,  bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									config ,  err  :=  globalBucketMetadataSys . GetReplicationConfig ( ctx ,  bucket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									configData ,  err  :=  xml . Marshal ( config ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseXML ( w ,  configData ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// DeleteBucketReplicationConfigHandler - DELETE Bucket replication config.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ----------
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( api  objectAPIHandlers )  DeleteBucketReplicationConfigHandler ( w  http . ResponseWriter ,  r  * http . Request )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  newContext ( r ,  w ,  "DeleteBucketReplicationConfig" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  logger . AuditLog ( w ,  r ,  "DeleteBucketReplicationConfig" ,  mustGetClaimsFromToken ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									vars  :=  mux . Vars ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bucket  :=  vars [ "bucket" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									objectAPI  :=  api . ObjectAPI ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  objectAPI  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( ErrServerNotInitialized ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  s3Error  :=  checkRequestAuthType ( ctx ,  r ,  policy . PutReplicationConfigurationAction ,  bucket ,  "" ) ;  s3Error  !=  ErrNone  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  errorCodes . ToAPIErr ( s3Error ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Check if bucket exists.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  _ ,  err  :=  objectAPI . GetBucketInfo ( ctx ,  bucket ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  globalBucketMetadataSys . Update ( bucket ,  bucketReplicationConfig ,  nil ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										writeErrorResponse ( ctx ,  w ,  toAPIError ( ctx ,  err ) ,  r . URL ,  guessIsBrowserReq ( r ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Write success response.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									writeSuccessResponseHeadersOnly ( w ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}