use super::*;
use super::*;
pub(crate) fn xml_response(status: u16, body: String) -> S3HttpResponse {
S3HttpResponse::new(status)
.with_header("content-type", "application/xml")
.with_header("content-length", body.len().to_string())
.with_body(body.into_bytes())
}
pub(crate) fn list_buckets_xml(buckets: &[Bucket]) -> String {
let bucket_entries = buckets
.iter()
.map(|bucket| {
format!(
"<Bucket><Name>{}</Name><CreationDate>{}</CreationDate></Bucket>",
xml_escape(&bucket.name),
xml_escape(&bucket.creation_date)
)
})
.collect::<String>();
format!("<ListAllMyBucketsResult><Buckets>{bucket_entries}</Buckets></ListAllMyBucketsResult>")
}
pub(crate) fn list_directory_buckets_xml(result: &ListDirectoryBucketsResult) -> String {
let buckets = result
.buckets
.iter()
.map(|bucket| {
let info = bucket.bucket_info.as_ref();
format!(
"<Bucket><BucketArn>{}</BucketArn><BucketRegion>{}</BucketRegion><CreationDate>{}</CreationDate><Name>{}</Name></Bucket>",
xml_escape(info.and_then(|value| value.bucket_arn.as_deref()).unwrap_or_default()),
xml_escape(info.and_then(|value| value.bucket_region.as_deref()).unwrap_or_default()),
xml_escape(&bucket.creation_date),
xml_escape(&bucket.name)
)
})
.collect::<String>();
let continuation_token = result
.continuation_token
.as_ref()
.map(|value| {
format!(
"<ContinuationToken>{}</ContinuationToken>",
xml_escape(value)
)
})
.unwrap_or_default();
format!(
"<ListAllMyDirectoryBucketsResult><Buckets>{buckets}</Buckets>{continuation_token}</ListAllMyDirectoryBucketsResult>"
)
}
pub(crate) fn bucket_versioning_xml(result: &BucketVersioningResult) -> String {
format!(
"<VersioningConfiguration><Status>{}</Status></VersioningConfiguration>",
versioning_status_text(result.status)
)
}
pub(crate) fn bucket_location_xml(result: &BucketLocationResult) -> String {
let constraint = if result.region == DEFAULT_BUCKET_REGION {
String::new()
} else {
xml_escape(&result.region)
};
format!("<LocationConstraint>{constraint}</LocationConstraint>")
}
pub(crate) fn bucket_cors_xml(result: &BucketCorsResult) -> String {
let rules = result
.rules
.iter()
.map(|rule| {
let origins = rule
.allowed_origins
.iter()
.map(|value| format!("<AllowedOrigin>{}</AllowedOrigin>", xml_escape(value)))
.collect::<String>();
let methods = rule
.allowed_methods
.iter()
.map(|value| format!("<AllowedMethod>{}</AllowedMethod>", xml_escape(value)))
.collect::<String>();
let headers = rule
.allowed_headers
.iter()
.map(|value| format!("<AllowedHeader>{}</AllowedHeader>", xml_escape(value)))
.collect::<String>();
let expose = rule
.expose_headers
.iter()
.map(|value| format!("<ExposeHeader>{}</ExposeHeader>", xml_escape(value)))
.collect::<String>();
let max_age = rule
.max_age_seconds
.map(|value| format!("<MaxAgeSeconds>{value}</MaxAgeSeconds>"))
.unwrap_or_default();
format!("<CORSRule>{origins}{methods}{headers}{expose}{max_age}</CORSRule>")
})
.collect::<String>();
format!("<CORSConfiguration>{rules}</CORSConfiguration>")
}
pub(crate) fn bucket_logging_xml(logging: Option<&str>) -> String {
logging
.map(parse_bucket_logging_status)
.transpose()
.expect("stored bucket logging XML must remain valid")
.map(|status| bucket_logging_status_xml(&status))
.unwrap_or_else(|| "<BucketLoggingStatus></BucketLoggingStatus>".to_string())
}
pub(crate) fn bucket_logging_status_xml(status: &BucketLoggingStatus) -> String {
let logging_enabled = status
.logging_enabled
.as_ref()
.map(|logging| {
format!(
"<LoggingEnabled><TargetBucket>{}</TargetBucket><TargetPrefix>{}</TargetPrefix></LoggingEnabled>",
xml_escape(&logging.target_bucket),
xml_escape(&logging.target_prefix)
)
})
.unwrap_or_default();
format!("<BucketLoggingStatus>{logging_enabled}</BucketLoggingStatus>")
}
pub(crate) fn bucket_website_configuration_xml(result: &BucketWebsiteConfiguration) -> String {
let error_document = result
.error_document_key
.as_ref()
.map(|key| {
format!(
"<ErrorDocument><Key>{}</Key></ErrorDocument>",
xml_escape(key)
)
})
.unwrap_or_default();
let routing_rules = result
.routing_rules
.iter()
.map(|rule| {
let condition = Condition {
key_prefix_equals: rule.condition_key_prefix_equals.clone(),
}
.key_prefix_equals
.as_ref()
.map(|prefix| {
format!(
"<Condition><KeyPrefixEquals>{}</KeyPrefixEquals></Condition>",
xml_escape(prefix)
)
})
.unwrap_or_default();
let host_name = rule
.redirect_host_name
.as_ref()
.map(|value| format!("<HostName>{}</HostName>", xml_escape(value)))
.unwrap_or_default();
let replace_prefix = rule
.redirect_replace_key_prefix_with
.as_ref()
.map(|value| {
format!(
"<ReplaceKeyPrefixWith>{}</ReplaceKeyPrefixWith>",
xml_escape(value)
)
})
.unwrap_or_default();
let code = rule
.redirect_http_redirect_code
.as_ref()
.map(|value| format!("<HttpRedirectCode>{}</HttpRedirectCode>", xml_escape(value)))
.unwrap_or_default();
format!(
"<RoutingRule>{condition}<Redirect>{host_name}{replace_prefix}{code}</Redirect></RoutingRule>"
)
})
.collect::<String>();
let routing_rules = if routing_rules.is_empty() {
String::new()
} else {
format!("<RoutingRules>{routing_rules}</RoutingRules>")
};
format!(
"<WebsiteConfiguration><IndexDocument><Suffix>{}</Suffix></IndexDocument>{error_document}{routing_rules}</WebsiteConfiguration>",
xml_escape(&result.index_document_suffix)
)
}
pub(crate) fn bucket_tagging_xml(result: &BucketTaggingResult) -> String {
tags_xml(&result.tags)
}
pub(crate) fn bucket_accelerate_configuration_xml(
result: &BucketAccelerateConfiguration,
) -> String {
format!(
"<AccelerateConfiguration><Status>{}</Status></AccelerateConfiguration>",
xml_escape(&result.status)
)
}
pub(crate) fn bucket_policy_status_xml(result: &BucketPolicyStatus) -> String {
format!(
"<PolicyStatus><IsPublic>{}</IsPublic></PolicyStatus>",
if result.is_public { "true" } else { "false" }
)
}
pub(crate) fn bucket_abac_status_xml(result: &BucketAbacStatus) -> String {
format!(
"<AbacStatus><Status>{}</Status></AbacStatus>",
xml_escape(&result.status)
)
}
pub(crate) fn bucket_request_payment_xml(result: &BucketRequestPaymentConfiguration) -> String {
format!(
"<RequestPaymentConfiguration><Payer>{}</Payer></RequestPaymentConfiguration>",
xml_escape(&result.payer)
)
}
pub(crate) fn create_session_result_xml(result: &CreateSessionResult) -> String {
format!(
"<CreateSessionResult><Credentials><AccessKeyId>{}</AccessKeyId><Expiration>{}</Expiration><SecretAccessKey>{}</SecretAccessKey><SessionToken>{}</SessionToken></Credentials></CreateSessionResult>",
xml_escape(&result.credentials.access_key_id),
xml_escape(&result.credentials.expiration),
xml_escape(&result.credentials.secret_access_key),
xml_escape(&result.credentials.session_token),
)
}
pub(crate) fn public_access_block_configuration_xml(
result: &PublicAccessBlockConfiguration,
) -> String {
let bool_xml = |value: bool| if value { "true" } else { "false" };
format!(
"<PublicAccessBlockConfiguration><BlockPublicAcls>{}</BlockPublicAcls><IgnorePublicAcls>{}</IgnorePublicAcls><BlockPublicPolicy>{}</BlockPublicPolicy><RestrictPublicBuckets>{}</RestrictPublicBuckets></PublicAccessBlockConfiguration>",
bool_xml(result.block_public_acls),
bool_xml(result.ignore_public_acls),
bool_xml(result.block_public_policy),
bool_xml(result.restrict_public_buckets)
)
}