dispokit

HTTP Content-Disposition parser, serializer, filename encoder, and safety diagnostics for MoonBit.

http
content-disposition
filename
rfc6266
rfc8187
moonbit
moon add BenPaoBaMingWangXing/dispokit@0.1.1
Download zip
Version
0.1.1
License
MIT
Last updated
7 days ago
Downloads
4
README

#dispokit

dispokit 是一个 MoonBit 原生的 HTTP Content-Disposition 工具库,面向下载服务、上传网关、对象存储代理、Web 框架和测试工具,提供 header 解析、生成、RFC 5987/RFC 8187 文件名编码、安全文件名规范化、风险诊断、兼容性检查和批量审计能力。

包名:BenPaoBaMingWangXing/dispokit

#功能

  • 解析 attachmentinlineform-data 以及扩展 disposition type。
  • 支持普通参数和 filename*= 扩展参数,覆盖 UTF-8 与 ISO-8859-1 解码。
  • 生成可直接用于 HTTP 响应的 Content-Disposition header。
  • 规范化下载文件名,处理路径穿越、控制字符、Windows 保留设备名、隐藏文件、过长文件名等风险。
  • 提供 lint/review/report API,把语法问题和安全问题转成稳定诊断码。
  • 提供 audit gate API,把批量审计结果转换为可用于 CI、网关和报告模式的通过/阻断决策。
  • 提供 download profile,根据扩展名和 Content-Type 判断文件类型、风险等级和 inline/attachment 策略。
  • 提供 repair API,将外部输入 header 规范化为更安全、可序列化的 header。
  • 提供现代客户端、老客户端、浏览器下载、multipart 解析器、对象存储网关等兼容性检查。
  • 包含 4000 行以上有效 MoonBit 代码、59 个测试和两个可运行示例。

#安装

moon add BenPaoBaMingWangXing/dispokit

moon.pkg 中导入:

import {
"BenPaoBaMingWangXing/dispokit" @dispokit,
}

#快速示例

fn main {
let header = @dispokit.attachment("季度 报告.csv").to_header()
println(header)
match @dispokit.safe_filename_from_header(header) {
Ok(report) => println(report.value)
Err(err) => println(err.message)
}
}

输出示例:

attachment; filename="季度 报告.csv"; filename*=UTF-8''%E5%AD%A3%E5%BA%A6%20%E6%8A%A5%E5%91%8A.csv 季度 报告.csv

#常用 API

解析与生成:

  • parse_header(header)
  • parse_header_strict(header)
  • attachment(filename)
  • inline()
  • form_data(name, filename?)
  • serialize(disposition)

文件名安全:

  • sanitize_filename(filename)
  • sanitize_filename_with_policy(filename, policy)
  • sanitize_filename_preserve_extension(filename, policy)
  • safe_filename_from_header(header)
  • filename_ascii_fallback(filename)

审计与报告:

  • lint_header(header)
  • lint_headers(headers)
  • summarize_reviews(reviews)
  • reviews_to_text(reviews)
  • reviews_to_markdown(reviews)
  • reviews_to_json(reviews)
  • evaluate_audit_gate(reviews)
  • evaluate_headers_gate(headers)
  • evaluate_audit_gate_with_policy(reviews, policy)
  • AuditGatePolicy::strict()
  • AuditGatePolicy::download_gateway()
  • AuditGatePolicy::report_only()

下载准备:

  • prepare_download(request)
  • DownloadRequest::attachment(filename)
  • DownloadRequest::inline_preview(filename, content_type?)
  • DownloadRequest::from_content_type(content_type)

修复与兼容性:

  • repair_header(header)
  • canonicalize_header(header)
  • check_compatibility(header, profile)
  • compatibility_matrix(header)

更完整的 API 说明见 docs/API.md

#运行

moon check moon build moon test moon run cmd/main moon run cmd/audit moon publish --dry-run

当前本地验证结果:

  • moon check 通过
  • moon build 通过
  • moon test 通过,59 个测试全部通过
  • moon run cmd/main 通过
  • moon run cmd/audit 通过

#项目边界

dispokit 聚焦 Content-Disposition 和 HTTP 下载/上传文件名处理,不实现完整 HTTP 服务器、不解析 multipart body、不做文件系统写入、不做 MIME 嗅探。文件类型和风险判断基于扩展名与显式 Content-Type,只作为网关和应用层策略输入。

#开源许可

本项目采用 MIT License。项目为原创 MoonBit 实现,除 MoonBit core 标准库外不包含第三方运行时代码。

#
AuditGatePolicy

pub(all) struct AuditGatePolicy {
max_warnings : Int
max_errors : Int
allow_needs_attention : Bool
allow_filename_changes : Bool
allow_rejected_headers : Bool
} derive(Eq,
Debug
)

Policy used to convert a batch review into a CI or gateway decision.

#
AuditGatePolicy::download_gateway

fn AuditGatePolicy::download_gateway() -> AuditGatePolicy

#
AuditGatePolicy::report_only

fn AuditGatePolicy::report_only() -> AuditGatePolicy

#
AuditGatePolicy::strict

#
AuditGatePolicy::with_filename_changes

fn AuditGatePolicy::with_filename_changes(self : AuditGatePolicy, allowed : Bool) -> AuditGatePolicy

#
AuditGatePolicy::with_max_errors

fn AuditGatePolicy::with_max_errors(self : AuditGatePolicy, max_errors : Int) -> AuditGatePolicy

#
AuditGatePolicy::with_max_warnings

fn AuditGatePolicy::with_max_warnings(self : AuditGatePolicy, max_warnings : Int) -> AuditGatePolicy

#
AuditGatePolicy::with_needs_attention

fn AuditGatePolicy::with_needs_attention(self : AuditGatePolicy, allowed : Bool) -> AuditGatePolicy

#
AuditGatePolicy::with_rejected_headers

fn AuditGatePolicy::with_rejected_headers(self : AuditGatePolicy, allowed : Bool) -> AuditGatePolicy

#
AuditGateResult

pub(all) struct AuditGateResult {
accepted : Bool
status : ReviewStatus
summary : AuditSummary
reasons : Array[String]
} derive(Eq,
Debug
)

Decision produced by applying an AuditGatePolicy to review results.

#
AuditGateResult::reason_text

fn AuditGateResult::reason_text(self : AuditGateResult) -> String

#
AuditGateResult::to_text

fn AuditGateResult::to_text(self : AuditGateResult) -> String

#
AuditSummary

pub(all) struct AuditSummary {
total : Int
accepted : Int
needs_attention : Int
rejected : Int
warnings : Int
errors : Int
filenames_changed : Int
} derive(Eq,
Debug
)

Aggregate counters for a batch of header reviews.

#
AuditSummary::clean_count

fn AuditSummary::clean_count(self : AuditSummary) -> Int

#
AuditSummary::has_attention_items

fn AuditSummary::has_attention_items(self : AuditSummary) -> Bool

#
AuditSummary::has_failures

fn AuditSummary::has_failures(self : AuditSummary) -> Bool

#
AuditSummary::is_clean

fn AuditSummary::is_clean(self : AuditSummary) -> Bool

#
AuditSummary::to_text

fn AuditSummary::to_text(self : AuditSummary) -> String

#
ClientProfile

pub(all) enum ClientProfile {
ModernHttpClient
LegacyHttpClient
BrowserDownload
MultipartFormParser
ObjectStorageGateway
} derive(Eq,
Debug
)

#
ClientProfile::name

fn ClientProfile::name(self : ClientProfile) -> String

#
CompatibilityReport

pub(all) struct CompatibilityReport {
profile : ClientProfile
header : String
compatible : Bool
recommendations : Array[Recommendation]
} derive(Eq,
Debug
)

#
CompatibilityReport::status

#
CompatibilityReport::to_text

fn CompatibilityReport::to_text(self : CompatibilityReport) -> String

#
DecodedValue

type DecodedValue derive(Eq,
Debug
)

#
Diagnostic

pub(all) struct Diagnostic {
code : DiagnosticCode
severity : Severity
message : String
offset : Int?
} derive(Eq,
Debug
)

A parser or policy diagnostic with optional UTF-16 offset in the input.

#
Diagnostic::make

fn Diagnostic::make(code : DiagnosticCode, severity : Severity, message : String, offset : Int?) -> Diagnostic

#
Diagnostic::to_json

fn Diagnostic::to_json(self : Diagnostic) -> String

#
Diagnostic::to_text

fn Diagnostic::to_text(self : Diagnostic) -> String

#
DiagnosticCode

pub(all) enum DiagnosticCode {
EmptyHeader
InvalidDisposition
InvalidParameterName
MissingEquals
MissingValue
UnterminatedQuote
BadEscape
DuplicateParameter
InvalidPercentEncoding
InvalidExtendedValue
UnsupportedCharset
UnsafeFilename
PathSegmentStripped
ReservedName
EmptyFilename
LengthReduced
ControlCharacter
} derive(Eq,
Debug
)

Stable machine-readable diagnostic codes.

#
DiagnosticCode::name

fn DiagnosticCode::name(self : DiagnosticCode) -> String

#
Disposition

pub(all) struct Disposition {
kind : DispositionKind
params : Array[Parameter]
diagnostics : Array[Diagnostic]
} derive(Eq,
Debug
)

Parsed header plus recoverable diagnostics.

#
Disposition::extended_filename

fn Disposition::extended_filename(self : Disposition) -> String?

#
Disposition::filename

fn Disposition::filename(self : Disposition) -> String?

#
Disposition::find_param

fn Disposition::find_param(self : Disposition, name : String) -> Parameter?

#
Disposition::get_param

fn Disposition::get_param(self : Disposition, name : String) -> String?

#
Disposition::has_errors

fn Disposition::has_errors(self : Disposition) -> Bool

#
Disposition::has_param

fn Disposition::has_param(self : Disposition, name : String) -> Bool

#
Disposition::is_attachment

fn Disposition::is_attachment(self : Disposition) -> Bool

#
Disposition::is_form_data

fn Disposition::is_form_data(self : Disposition) -> Bool

#
Disposition::is_inline

fn Disposition::is_inline(self : Disposition) -> Bool

#
Disposition::name

fn Disposition::name(self : Disposition) -> String?

#
Disposition::params_named

fn Disposition::params_named(self : Disposition, name : String) -> Array[Parameter]

#
Disposition::plain_filename

fn Disposition::plain_filename(self : Disposition) -> String?

#
Disposition::to_builder

fn Disposition::to_builder(self : Disposition) -> DispositionBuilder

#
Disposition::to_header

fn Disposition::to_header(self : Disposition) -> String

#
Disposition::with_param

fn Disposition::with_param(self : Disposition, name : String, value : String) -> Disposition

#
Disposition::without_param

fn Disposition::without_param(self : Disposition, name : String) -> Disposition

#
DispositionBuilder

pub(all) struct DispositionBuilder {
kind : DispositionKind
params : Array[Parameter]
diagnostics : Array[Diagnostic]
} derive(Eq,
Debug
)

Mutable-style builder that returns a fresh builder for every operation.

#
DispositionBuilder::attachment

#
DispositionBuilder::build

#
DispositionBuilder::form_data

#
DispositionBuilder::inline

#
DispositionBuilder::new

#
DispositionBuilder::to_header

fn DispositionBuilder::to_header(self : DispositionBuilder) -> String

#
DispositionBuilder::with_extended_param

fn DispositionBuilder::with_extended_param(self : DispositionBuilder, name : String, value : String, charset? : String, language? : String) -> DispositionBuilder

#
DispositionBuilder::with_filename

fn DispositionBuilder::with_filename(self : DispositionBuilder, filename : String) -> DispositionBuilder

#
DispositionBuilder::with_filename_policy

fn DispositionBuilder::with_filename_policy(self : DispositionBuilder, filename : String, policy : FilenamePolicy) -> DispositionBuilder

#
DispositionBuilder::with_form_name

fn DispositionBuilder::with_form_name(self : DispositionBuilder, name : String) -> DispositionBuilder

#
DispositionBuilder::with_kind

#
DispositionBuilder::with_param

fn DispositionBuilder::with_param(self : DispositionBuilder, name : String, value : String) -> DispositionBuilder

#
DispositionBuilder::without_param

fn DispositionBuilder::without_param(self : DispositionBuilder, name : String) -> DispositionBuilder

#
DispositionKind

pub(all) enum DispositionKind {
Inline
Attachment
FormData
Other(String)
} derive(Eq,
Debug
)

Registered and extension disposition kinds from HTTP Content-Disposition.

#
DispositionKind::from_token

fn DispositionKind::from_token(token : String) -> DispositionKind

#
DispositionKind::to_token

fn DispositionKind::to_token(self : DispositionKind) -> String

#
DownloadRequest

pub(all) struct DownloadRequest {
filename : String?
content_type : String?
prefer_inline : Bool
} derive(Eq,
Debug
)

#
DownloadRequest::attachment

fn DownloadRequest::attachment(filename : String) -> DownloadRequest

#
DownloadRequest::from_content_type

fn DownloadRequest::from_content_type(content_type : String) -> DownloadRequest

#
DownloadRequest::inline_preview

fn DownloadRequest::inline_preview(filename : String, content_type? : String) -> DownloadRequest

#
ExtensionRisk

pub(all) enum ExtensionRisk {
LowRisk
MediumRisk
HighRisk
UnknownRisk
} derive(Eq,
Debug
)

#
ExtensionRisk::name

fn ExtensionRisk::name(self : ExtensionRisk) -> String

#
FileKind

pub(all) enum FileKind {
NoExtension
TextFile
DocumentFile
SpreadsheetFile
PresentationFile
ImageFile
AudioFile
VideoFile
ArchiveFile
CodeFile
ExecutableFile
FontFile
DataFile
UnknownFile
} derive(Eq,
Debug
)

#
FileKind::name

fn FileKind::name(self : FileKind) -> String

#
FilenamePolicy

pub(all) struct FilenamePolicy {
replacement : String
max_length : Int
default_name : String
allow_hidden : Bool
} derive(Eq,
Debug
)

Policy for sanitize_filename_with_policy.

#
FilenamePolicy::default

#
FilenamePolicy::multipart_upload

fn FilenamePolicy::multipart_upload() -> FilenamePolicy

#
FilenamePolicy::object_storage_key

fn FilenamePolicy::object_storage_key() -> FilenamePolicy

#
FilenamePolicy::strict_download

fn FilenamePolicy::strict_download() -> FilenamePolicy

#
FilenamePolicy::validate

#
FilenamePolicy::with_default_name

fn FilenamePolicy::with_default_name(self : FilenamePolicy, default_name : String) -> FilenamePolicy

#
FilenamePolicy::with_hidden_files

fn FilenamePolicy::with_hidden_files(self : FilenamePolicy, allow_hidden : Bool) -> FilenamePolicy

#
FilenamePolicy::with_max_length

fn FilenamePolicy::with_max_length(self : FilenamePolicy, max_length : Int) -> FilenamePolicy

#
FilenamePolicy::with_replacement

fn FilenamePolicy::with_replacement(self : FilenamePolicy, replacement : String) -> FilenamePolicy

#
FilenameReport

pub(all) struct FilenameReport {
value : String
original : String
changed : Bool
diagnostics : Array[Diagnostic]
} derive(Eq,
Debug
)

Result of filename normalization.

#
FilenameReport::to_json

fn FilenameReport::to_json(self : FilenameReport) -> String

#
FilenameReport::to_text

fn FilenameReport::to_text(self : FilenameReport) -> String

#
HeaderRepair

pub(all) struct HeaderRepair {
input : String
output : String
changed : Bool
review : HeaderReview
disposition : Disposition
filename : FilenameReport?
} derive(Eq,
Debug
)

#
HeaderRepair::has_filename_change

fn HeaderRepair::has_filename_change(self : HeaderRepair) -> Bool

#
HeaderRepair::is_lossless

fn HeaderRepair::is_lossless(self : HeaderRepair) -> Bool

#
HeaderRepair::to_text

fn HeaderRepair::to_text(self : HeaderRepair) -> String

#
HeaderReview

pub(all) struct HeaderReview {
header : String
disposition : Disposition?
filename : FilenameReport?
recommendations : Array[Recommendation]
status : ReviewStatus
} derive(Eq,
Debug
)

Lint result for one Content-Disposition header.

#
HeaderReview::disposition_kind

fn HeaderReview::disposition_kind(self : HeaderReview) -> String?

#
HeaderReview::error_count

fn HeaderReview::error_count(self : HeaderReview) -> Int

#
HeaderReview::filename_value

fn HeaderReview::filename_value(self : HeaderReview) -> String?

#
HeaderReview::has_recommendation

fn HeaderReview::has_recommendation(self : HeaderReview, code : RecommendationCode) -> Bool

#
HeaderReview::is_ok

fn HeaderReview::is_ok(self : HeaderReview) -> Bool

#
HeaderReview::recommendations_by_severity

fn HeaderReview::recommendations_by_severity(self : HeaderReview, severity : Severity) -> Array[Recommendation]

#
HeaderReview::to_json

fn HeaderReview::to_json(self : HeaderReview) -> String

#
HeaderReview::to_markdown_row

fn HeaderReview::to_markdown_row(self : HeaderReview) -> String

#
HeaderReview::to_text

fn HeaderReview::to_text(self : HeaderReview) -> String

#
HeaderReview::warning_count

fn HeaderReview::warning_count(self : HeaderReview) -> Int

#
NormalizedDisposition

type NormalizedDisposition derive(Eq,
Debug
)

#
Parameter

pub(all) struct Parameter {
name : String
value : String
raw_name : String
raw_value : String
extended : Bool
charset : String?
language : String?
position : Int
} derive(Eq,
Debug
)

A single Content-Disposition parameter.

name is normalized to lowercase and has the RFC 5987 * suffix removed. extended records whether the parameter came from name*=....

#
Parameter::effective_name

fn Parameter::effective_name(self : Parameter) -> String

#
Parameter::extended

fn Parameter::extended(name : String, value : String, charset? : String, language? : String) -> Parameter

#
Parameter::is_filename

fn Parameter::is_filename(self : Parameter) -> Bool

#
Parameter::is_name

fn Parameter::is_name(self : Parameter) -> Bool

#
Parameter::plain

fn Parameter::plain(name : String, value : String) -> Parameter

#
ParseError

pub(all) struct ParseError {
code : DiagnosticCode
message : String
offset : Int?
} derive(Eq,
Debug
)

Fatal parse error returned by strict entry points.

#
ParseError::from_diagnostic

fn ParseError::from_diagnostic(d : Diagnostic) -> ParseError

#
ParsedValue

type ParsedValue derive(Eq,
Debug
)

#
PreparedDownload

pub(all) struct PreparedDownload {
header : String
disposition : Disposition
filename : FilenameReport
content_type : String?
extension : String?
file_kind : FileKind
risk : ExtensionRisk
recommendations : Array[Recommendation]
} derive(Eq,
Debug
)

#
PreparedDownload::has_high_risk_extension

fn PreparedDownload::has_high_risk_extension(self : PreparedDownload) -> Bool

#
PreparedDownload::is_attachment

fn PreparedDownload::is_attachment(self : PreparedDownload) -> Bool

#
PreparedDownload::is_inline

fn PreparedDownload::is_inline(self : PreparedDownload) -> Bool

#
Recommendation

pub(all) struct Recommendation {
code : RecommendationCode
severity : Severity
message : String
parameter : String?
value : String?
offset : Int?
} derive(Eq,
Debug
)

Human-oriented recommendation produced by linting.

#
Recommendation::make

fn Recommendation::make(code : RecommendationCode, severity : Severity, message : String, parameter : String?, value : String?, offset : Int?) -> Recommendation

#
Recommendation::to_json

fn Recommendation::to_json(self : Recommendation) -> String

#
Recommendation::to_text

fn Recommendation::to_text(self : Recommendation) -> String

#
RecommendationCode

pub(all) enum RecommendationCode {
PreferFilenameStar
AddAsciiFallback
SanitizeFilename
RemoveDuplicateParameter
FixSyntax
UseSupportedCharset
AddMultipartName
AvoidEmptyFilename
LimitFilenameLength
PreserveExplicitDisposition
ReviewFileExtension
AvoidExecutableDownload
PreferAttachmentDisposition
InferFilename
} derive(Eq,
Debug
)

Stable machine-readable recommendation codes.

#
RecommendationCode::name

fn RecommendationCode::name(self : RecommendationCode) -> String

#
ReviewStatus

pub(all) enum ReviewStatus {
Accepted
NeedsAttention
Rejected
} derive(Eq,
Debug
)

Overall result produced by header linting.

#
ReviewStatus::name

fn ReviewStatus::name(self : ReviewStatus) -> String

#
Severity

pub(all) enum Severity {
Note
Warning
Error
} derive(Eq,
Debug
)

Diagnostic severity used by parser and filename policy checks.

#
Severity::name

fn Severity::name(self : Severity) -> String

#
attachment

fn attachment(filename : String) -> Disposition

Build a safe attachment header for the supplied file name.

#
canonicalize_header

fn canonicalize_header(header : String) -> Result[String, ParseError]

#
canonicalize_header_loose

fn canonicalize_header_loose(header : String) -> Result[String, ParseError]

#
check_compatibility

fn check_compatibility(header : String, profile : ClientProfile) -> CompatibilityReport

#
classify_extension

fn classify_extension(extension : String) -> FileKind

#
classify_filename

fn classify_filename(filename : String) -> FileKind

#
compatibility_matrix

fn compatibility_matrix(header : String) -> Array[CompatibilityReport]

#
compatibility_matrix_to_text

fn compatibility_matrix_to_text(reports : Array[CompatibilityReport]) -> String

#
content_type_for_extension

fn content_type_for_extension(extension : String) -> String?

#
encode_ext_value

fn encode_ext_value(value : String, charset? : String, language? : String) -> String

#
encode_param_value

fn encode_param_value(value : String) -> String

#
evaluate_audit_gate

fn evaluate_audit_gate(reviews : Array[HeaderReview]) -> AuditGateResult

Evaluate a batch of already computed reviews with the strict default gate.

#
evaluate_audit_gate_with_policy

fn evaluate_audit_gate_with_policy(reviews : Array[HeaderReview], policy : AuditGatePolicy) -> AuditGateResult

Evaluate a batch of reviews against explicit warning, error and repair limits.

#
evaluate_headers_gate

fn evaluate_headers_gate(headers : Array[String]) -> AuditGateResult

Lint headers and evaluate them with the strict default gate.

#
evaluate_headers_gate_with_policy

fn evaluate_headers_gate_with_policy(headers : Array[String], filename_policy : FilenamePolicy, audit_policy : AuditGatePolicy) -> AuditGateResult

Lint headers with a filename policy and evaluate them with an audit policy.

#
extension_for_content_type

fn extension_for_content_type(content_type : String) -> String?

#
extension_risk

fn extension_risk(kind : FileKind, extension : String?) -> ExtensionRisk

#
filename_ascii_fallback

fn filename_ascii_fallback(filename : String) -> String

#
filename_extension

fn filename_extension(filename : String) -> String?

#
filename_has_extension

fn filename_has_extension(filename : String, extension : String) -> Bool

#
filename_stem

fn filename_stem(filename : String) -> String

#
form_data

fn form_data(name : String, filename? : String) -> Disposition

Build a form-data disposition for multipart form fields.

#
infer_filename_from_content_type

fn infer_filename_from_content_type(content_type : String?) -> String

#
inline

fn inline() -> Disposition

Build a minimal inline disposition.

#
inline_allowed_for_kind

fn inline_allowed_for_kind(kind : FileKind) -> Bool

#
is_probably_safe_filename

fn is_probably_safe_filename(filename : String) -> Bool

#
is_token

fn is_token(value : String) -> Bool

#
is_token_char

fn is_token_char(c : Char) -> Bool

#
lint_header

fn lint_header(header : String) -> HeaderReview

#
lint_header_with_policy

fn lint_header_with_policy(header : String, policy : FilenamePolicy) -> HeaderReview

#
lint_headers

fn lint_headers(headers : Array[String]) -> Array[HeaderReview]

#
lint_headers_with_policy

fn lint_headers_with_policy(headers : Array[String], policy : FilenamePolicy) -> Array[HeaderReview]

#
normalize_content_type

fn normalize_content_type(content_type : String) -> String

#
normalize_extension

fn normalize_extension(extension : String) -> String

#
normalize_param_name

fn normalize_param_name(name : String) -> String

#
parse_header

fn parse_header(header : String) -> Result[Disposition, ParseError]

Parse a HTTP Content-Disposition header into a structured value.

The parser accepts common recovery cases and records them in Disposition.diagnostics. Use parse_header_strict when diagnostics with severity Error should fail the parse.

#
parse_header_strict

fn parse_header_strict(header : String) -> Result[Disposition, ParseError]

Parse a header and reject any syntax or decoding error.

#
prepare_download

fn prepare_download(request : DownloadRequest) -> PreparedDownload

#
quote_string

fn quote_string(value : String) -> String

#
repair_header

fn repair_header(header : String) -> HeaderRepair

#
repair_header_with_policy

fn repair_header_with_policy(header : String, policy : FilenamePolicy) -> HeaderRepair

#
repair_headers

fn repair_headers(headers : Array[String]) -> Array[HeaderRepair]

#
repairs_to_headers

fn repairs_to_headers(repairs : Array[HeaderRepair]) -> Array[String]

#
repairs_to_text

fn repairs_to_text(repairs : Array[HeaderRepair]) -> String

#
reviews_by_status

fn reviews_by_status(reviews : Array[HeaderReview], status : ReviewStatus) -> Array[HeaderReview]

#
reviews_to_json

fn reviews_to_json(reviews : Array[HeaderReview]) -> String

#
reviews_to_markdown

fn reviews_to_markdown(reviews : Array[HeaderReview]) -> String

#
reviews_to_text

fn reviews_to_text(reviews : Array[HeaderReview]) -> String

#
reviews_with_filename_changes

fn reviews_with_filename_changes(reviews : Array[HeaderReview]) -> Array[HeaderReview]

#
reviews_with_recommendation

fn reviews_with_recommendation(reviews : Array[HeaderReview], code : RecommendationCode) -> Array[HeaderReview]

#
safe_filename_from_header

fn safe_filename_from_header(header : String) -> Result[FilenameReport, ParseError]

#
sanitize_filename

fn sanitize_filename(filename : String) -> FilenameReport

#
sanitize_filename_preserve_extension

fn sanitize_filename_preserve_extension(filename : String, policy : FilenamePolicy) -> FilenameReport

#
sanitize_filename_strict

fn sanitize_filename_strict(filename : String) -> FilenameReport

#
sanitize_filename_with_policy

fn sanitize_filename_with_policy(filename : String, policy : FilenamePolicy) -> FilenameReport

#
sanitize_object_key

fn sanitize_object_key(filename : String) -> FilenameReport

#
sanitize_upload_filename

fn sanitize_upload_filename(filename : String) -> FilenameReport

#
serialize

fn serialize(disposition : Disposition) -> String

#
serialize_param

fn serialize_param(param : Parameter) -> String

#
summarize_reviews

fn summarize_reviews(reviews : Array[HeaderReview]) -> AuditSummary