2020-07-03 13:52:04 +00:00
|
|
|
package layer
|
|
|
|
|
|
|
|
import (
|
2022-05-12 16:58:11 +00:00
|
|
|
"encoding/hex"
|
2021-07-28 13:27:06 +00:00
|
|
|
"fmt"
|
2020-08-03 11:48:33 +00:00
|
|
|
"os"
|
2020-10-24 13:09:22 +00:00
|
|
|
"strconv"
|
2020-07-03 13:52:04 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2023-03-07 14:38:08 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2020-07-03 13:52:04 +00:00
|
|
|
)
|
|
|
|
|
2021-06-29 09:59:33 +00:00
|
|
|
// PathSeparator is a path components separator string.
|
|
|
|
const PathSeparator = string(os.PathSeparator)
|
2020-07-03 13:52:04 +00:00
|
|
|
|
2022-03-16 09:02:16 +00:00
|
|
|
func userHeaders(attrs []object.Attribute) map[string]string {
|
2020-10-19 01:04:37 +00:00
|
|
|
result := make(map[string]string, len(attrs))
|
2020-07-03 13:52:04 +00:00
|
|
|
|
2020-10-19 01:04:37 +00:00
|
|
|
for _, attr := range attrs {
|
2020-11-24 07:01:38 +00:00
|
|
|
result[attr.Key()] = attr.Value()
|
2020-07-03 13:52:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2022-07-22 16:54:11 +00:00
|
|
|
func objectInfoFromMeta(bkt *data.BucketInfo, meta *object.Object) *data.ObjectInfo {
|
2020-10-24 13:09:22 +00:00
|
|
|
var (
|
2021-06-29 09:59:33 +00:00
|
|
|
mimeType string
|
|
|
|
creation time.Time
|
2020-10-24 13:09:22 +00:00
|
|
|
)
|
2020-07-03 13:52:04 +00:00
|
|
|
|
2022-07-22 16:54:11 +00:00
|
|
|
headers := userHeaders(meta.Attributes())
|
2022-09-07 06:59:24 +00:00
|
|
|
delete(headers, object.AttributeFilePath)
|
2022-07-22 16:54:11 +00:00
|
|
|
if contentType, ok := headers[object.AttributeContentType]; ok {
|
2021-06-29 09:59:33 +00:00
|
|
|
mimeType = contentType
|
2022-07-22 16:54:11 +00:00
|
|
|
delete(headers, object.AttributeContentType)
|
2020-10-24 13:09:22 +00:00
|
|
|
}
|
2023-05-31 16:39:35 +00:00
|
|
|
if val, ok := headers[object.AttributeTimestamp]; !ok { //nolint:revive
|
2020-10-24 13:09:22 +00:00
|
|
|
// ignore empty value
|
|
|
|
} else if dt, err := strconv.ParseInt(val, 10, 64); err == nil {
|
|
|
|
creation = time.Unix(dt, 0)
|
2022-07-22 16:54:11 +00:00
|
|
|
delete(headers, object.AttributeTimestamp)
|
2021-01-14 17:39:48 +00:00
|
|
|
}
|
2020-08-03 11:48:33 +00:00
|
|
|
|
2022-04-25 09:57:58 +00:00
|
|
|
objID, _ := meta.ID()
|
|
|
|
payloadChecksum, _ := meta.PayloadChecksum()
|
2021-09-10 06:56:56 +00:00
|
|
|
return &data.ObjectInfo{
|
2024-01-17 14:26:02 +00:00
|
|
|
ID: objID,
|
|
|
|
CID: bkt.CID,
|
2021-08-13 14:13:14 +00:00
|
|
|
|
2023-06-13 09:34:19 +00:00
|
|
|
Bucket: bkt.Name,
|
|
|
|
Name: filepathFromObject(meta),
|
|
|
|
Created: creation,
|
|
|
|
ContentType: mimeType,
|
|
|
|
Headers: headers,
|
2024-03-01 14:11:07 +00:00
|
|
|
Owner: meta.OwnerID(),
|
2023-06-13 09:34:19 +00:00
|
|
|
Size: meta.PayloadSize(),
|
|
|
|
CreationEpoch: meta.CreationEpoch(),
|
|
|
|
HashSum: hex.EncodeToString(payloadChecksum.Value()),
|
2021-07-05 19:18:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-16 13:54:12 +00:00
|
|
|
func GetObjectSize(objInfo *data.ObjectInfo) (uint64, error) {
|
|
|
|
var err error
|
|
|
|
fullSize := objInfo.Size
|
|
|
|
|
|
|
|
if objInfo.Headers[AttributeDecryptedSize] != "" {
|
|
|
|
if fullSize, err = strconv.ParseUint(objInfo.Headers[AttributeDecryptedSize], 10, 64); err != nil {
|
|
|
|
return 0, fmt.Errorf("invalid decrypted size header: %w", err)
|
|
|
|
}
|
|
|
|
} else if objInfo.Headers[MultipartObjectSize] != "" {
|
|
|
|
if fullSize, err = strconv.ParseUint(objInfo.Headers[MultipartObjectSize], 10, 64); err != nil {
|
|
|
|
return 0, fmt.Errorf("invalid multipart size header: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullSize, nil
|
|
|
|
}
|
|
|
|
|
2022-08-11 08:48:58 +00:00
|
|
|
func FormEncryptionInfo(headers map[string]string) encryption.ObjectEncryption {
|
2022-08-01 16:52:09 +00:00
|
|
|
algorithm := headers[AttributeEncryptionAlgorithm]
|
2022-08-11 08:48:58 +00:00
|
|
|
return encryption.ObjectEncryption{
|
2022-08-01 16:52:09 +00:00
|
|
|
Enabled: len(algorithm) > 0,
|
|
|
|
Algorithm: algorithm,
|
|
|
|
HMACKey: headers[AttributeHMACKey],
|
|
|
|
HMACSalt: headers[AttributeHMACSalt],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-11 08:48:58 +00:00
|
|
|
func addEncryptionHeaders(meta map[string]string, enc encryption.Params) error {
|
2022-08-01 16:52:09 +00:00
|
|
|
meta[AttributeEncryptionAlgorithm] = AESEncryptionAlgorithm
|
|
|
|
hmacKey, hmacSalt, err := enc.HMAC()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("get hmac: %w", err)
|
|
|
|
}
|
|
|
|
meta[AttributeHMACKey] = hex.EncodeToString(hmacKey)
|
|
|
|
meta[AttributeHMACSalt] = hex.EncodeToString(hmacSalt)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-09-07 06:59:24 +00:00
|
|
|
func filepathFromObject(o *object.Object) string {
|
2020-11-24 07:01:38 +00:00
|
|
|
for _, attr := range o.Attributes() {
|
2022-09-07 06:59:24 +00:00
|
|
|
if attr.Key() == object.AttributeFilePath {
|
2021-06-29 09:59:33 +00:00
|
|
|
return attr.Value()
|
2020-10-19 01:04:37 +00:00
|
|
|
}
|
2020-07-03 13:52:04 +00:00
|
|
|
}
|
2022-04-25 09:57:58 +00:00
|
|
|
objID, _ := o.ID()
|
2022-05-25 17:25:43 +00:00
|
|
|
return objID.EncodeToString()
|
2021-01-14 17:39:48 +00:00
|
|
|
}
|
2020-07-03 13:52:04 +00:00
|
|
|
|
2022-04-13 16:56:58 +00:00
|
|
|
// NameFromString splits name into a base file name and a directory path.
|
2021-01-14 17:39:48 +00:00
|
|
|
func NameFromString(name string) (string, string) {
|
|
|
|
ind := strings.LastIndex(name, PathSeparator)
|
2020-07-03 13:52:04 +00:00
|
|
|
return name[ind+1:], name[:ind+1]
|
|
|
|
}
|