@ -1008,12 +1008,13 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
// Since we are rotating the keys, make sure to update the metadata.
// Since we are rotating the keys, make sure to update the metadata.
srcInfo . metadataOnly = true
srcInfo . metadataOnly = true
srcInfo . keyRotation = true
} else {
} else {
if isSourceEncrypted || isTargetEncrypted {
if isSourceEncrypted || isTargetEncrypted {
// We are not only copying just metadata instead
// We are not only copying just metadata instead
// we are creating a new object at this point, even
// we are creating a new object at this point, even
// if source and destination are same objects.
// if source and destination are same objects.
if ! srcInfo . metadataOnly {
if ! srcInfo . keyRotation {
srcInfo . metadataOnly = false
srcInfo . metadataOnly = false
}
}
}
}
@ -1858,15 +1859,14 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
actualPartSize = length
actualPartSize = length
var reader io . Reader
var reader io . Reader
var li ListPartsInfo
mi , err := objectAPI . GetMultipartInfo ( ctx , dstBucket , dstObject , uploadID , dstOpts )
li , err = objectAPI . ListObjectParts ( ctx , dstBucket , dstObject , uploadID , 0 , 1 , dstOpts )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
}
}
// Read compression metadata preserved in the init multipart for the decision.
// Read compression metadata preserved in the init multipart for the decision.
_ , isCompressed := l i. UserDefined [ ReservedMetadataPrefix + "compression" ]
_ , isCompressed := m i. UserDefined [ ReservedMetadataPrefix + "compression" ]
// Compress only if the compression is enabled during initial multipart.
// Compress only if the compression is enabled during initial multipart.
if isCompressed {
if isCompressed {
s2c := newS2CompressReader ( gr )
s2c := newS2CompressReader ( gr )
@ -1883,7 +1883,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
return
return
}
}
dstOpts , err = copyDstOpts ( ctx , r , dstBucket , dstObject , l i. UserDefined )
dstOpts , err = copyDstOpts ( ctx , r , dstBucket , dstObject , m i. UserDefined )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
@ -1892,14 +1892,14 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
rawReader := srcInfo . Reader
rawReader := srcInfo . Reader
pReader := NewPutObjReader ( rawReader , nil , nil )
pReader := NewPutObjReader ( rawReader , nil , nil )
isEncrypted := crypto . IsEncrypted ( l i. UserDefined )
isEncrypted := crypto . IsEncrypted ( m i. UserDefined )
var objectEncryptionKey crypto . ObjectKey
var objectEncryptionKey crypto . ObjectKey
if objectAPI . IsEncryptionSupported ( ) && ! isCompressed && isEncrypted {
if objectAPI . IsEncryptionSupported ( ) && ! isCompressed && isEncrypted {
if ! crypto . SSEC . IsRequested ( r . Header ) && crypto . SSEC . IsEncrypted ( l i. UserDefined ) {
if ! crypto . SSEC . IsRequested ( r . Header ) && crypto . SSEC . IsEncrypted ( m i. UserDefined ) {
writeErrorResponse ( ctx , w , errorCodes . ToAPIErr ( ErrSSEMultipartEncrypted ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , errorCodes . ToAPIErr ( ErrSSEMultipartEncrypted ) , r . URL , guessIsBrowserReq ( r ) )
return
return
}
}
if crypto . S3 . IsEncrypted ( l i. UserDefined ) && crypto . SSEC . IsRequested ( r . Header ) {
if crypto . S3 . IsEncrypted ( m i. UserDefined ) && crypto . SSEC . IsRequested ( r . Header ) {
writeErrorResponse ( ctx , w , errorCodes . ToAPIErr ( ErrSSEMultipartEncrypted ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , errorCodes . ToAPIErr ( ErrSSEMultipartEncrypted ) , r . URL , guessIsBrowserReq ( r ) )
return
return
}
}
@ -1911,7 +1911,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
return
return
}
}
}
}
key , err = decryptObjectInfo ( key , dstBucket , dstObject , l i. UserDefined )
key , err = decryptObjectInfo ( key , dstBucket , dstObject , m i. UserDefined )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
@ -2094,15 +2094,15 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
return
return
}
}
}
}
var li ListPartsInfo
li , err = objectAPI . ListObjectParts ( ctx , bucket , object , uploadID , 0 , 1 , opts )
mi , err := objectAPI . GetMultipartInfo ( ctx , bucket , object , uploadID , opts )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
}
}
// Read compression metadata preserved in the init multipart for the decision.
// Read compression metadata preserved in the init multipart for the decision.
_ , isCompressed := l i. UserDefined [ ReservedMetadataPrefix + "compression" ]
_ , isCompressed := m i. UserDefined [ ReservedMetadataPrefix + "compression" ]
if objectAPI . IsCompressionSupported ( ) && isCompressed {
if objectAPI . IsCompressionSupported ( ) && isCompressed {
actualReader , err := hash . NewReader ( reader , size , md5hex , sha256hex , actualSize , globalCLIContext . StrictS3Compat )
actualReader , err := hash . NewReader ( reader , size , md5hex , sha256hex , actualSize , globalCLIContext . StrictS3Compat )
@ -2128,15 +2128,15 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
rawReader := hashReader
rawReader := hashReader
pReader := NewPutObjReader ( rawReader , nil , nil )
pReader := NewPutObjReader ( rawReader , nil , nil )
isEncrypted := crypto . IsEncrypted ( l i. UserDefined )
isEncrypted := crypto . IsEncrypted ( m i. UserDefined )
var objectEncryptionKey crypto . ObjectKey
var objectEncryptionKey crypto . ObjectKey
if objectAPI . IsEncryptionSupported ( ) && ! isCompressed && isEncrypted {
if objectAPI . IsEncryptionSupported ( ) && ! isCompressed && isEncrypted {
if ! crypto . SSEC . IsRequested ( r . Header ) && crypto . SSEC . IsEncrypted ( l i. UserDefined ) {
if ! crypto . SSEC . IsRequested ( r . Header ) && crypto . SSEC . IsEncrypted ( m i. UserDefined ) {
writeErrorResponse ( ctx , w , errorCodes . ToAPIErr ( ErrSSEMultipartEncrypted ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , errorCodes . ToAPIErr ( ErrSSEMultipartEncrypted ) , r . URL , guessIsBrowserReq ( r ) )
return
return
}
}
opts , err = putOpts ( ctx , r , bucket , object , l i. UserDefined )
opts , err = putOpts ( ctx , r , bucket , object , m i. UserDefined )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
@ -2152,7 +2152,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
}
}
// Calculating object encryption key
// Calculating object encryption key
key , err = decryptObjectInfo ( key , bucket , object , l i. UserDefined )
key , err = decryptObjectInfo ( key , bucket , object , m i. UserDefined )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
@ -2438,19 +2438,18 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
var opts ObjectOptions
var opts ObjectOptions
var isEncrypted , ssec bool
var isEncrypted , ssec bool
if objectAPI . IsEncryptionSupported ( ) {
if objectAPI . IsEncryptionSupported ( ) {
var li ListPartsInfo
mi , err := objectAPI . GetMultipartInfo ( ctx , bucket , object , uploadID , opts )
li , err = objectAPI . ListObjectParts ( ctx , bucket , object , uploadID , 0 , 1 , opts )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
}
}
if crypto . IsEncrypted ( l i. UserDefined ) {
if crypto . IsEncrypted ( m i. UserDefined ) {
var key [ ] byte
var key [ ] byte
isEncrypted = true
isEncrypted = true
ssec = crypto . SSEC . IsEncrypted ( l i. UserDefined )
ssec = crypto . SSEC . IsEncrypted ( m i. UserDefined )
if crypto . S3 . IsEncrypted ( l i. UserDefined ) {
if crypto . S3 . IsEncrypted ( m i. UserDefined ) {
// Calculating object encryption key
// Calculating object encryption key
objectEncryptionKey , err = decryptObjectInfo ( key , bucket , object , l i. UserDefined )
objectEncryptionKey , err = decryptObjectInfo ( key , bucket , object , m i. UserDefined )
if err != nil {
if err != nil {
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
return
return
@ -2461,21 +2460,14 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
partsMap := make ( map [ string ] PartInfo )
partsMap := make ( map [ string ] PartInfo )
if isEncrypted {
if isEncrypted {
var partNumberMarker int
maxParts := 10000
maxParts := 1000
listPartsInfo , err := objectAPI . ListObjectParts ( ctx , bucket , object , uploadID , 0 , maxParts , opts )
for {
if err != nil {
listPartsInfo , err := objectAPI . ListObjectParts ( ctx , bucket , object , uploadID , partNumberMarker , maxParts , opts )
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
if err != nil {
return
writeErrorResponse ( ctx , w , toAPIError ( ctx , err ) , r . URL , guessIsBrowserReq ( r ) )
}
return
for _ , part := range listPartsInfo . Parts {
}
partsMap [ strconv . Itoa ( part . PartNumber ) ] = part
for _ , part := range listPartsInfo . Parts {
partsMap [ strconv . Itoa ( part . PartNumber ) ] = part
}
partNumberMarker = listPartsInfo . NextPartNumberMarker
if ! listPartsInfo . IsTruncated {
break
}
}
}
}
}