130 lines
3.6 KiB
Go
130 lines
3.6 KiB
Go
package aviation
|
|||
|
|
|
||
|
|
import "fmt"
|
||
|
|
|
||
|
|
// Validation limits based on ICAO and AFTN standards
|
||
|
|
const (
|
||
|
|
// MaxTelegramSize is the maximum size for an AFTN telegram (ICAO standard)
|
||
|
|
MaxTelegramSize = 1800
|
||
|
|
|
||
|
|
// MaxHeaderLines is the maximum number of lines allowed in the header section
|
||
|
|
MaxHeaderLines = 20
|
||
|
|
|
||
|
|
// MaxBodySize is the maximum size for the telegram body
|
||
|
|
MaxBodySize = 1500
|
||
|
|
|
||
|
|
// MaxTokenCount is the maximum number of tokens allowed to prevent tokenizer abuse
|
||
|
|
MaxTokenCount = 500
|
||
|
|
)
|
||
|
|
|
||
|
|
// ValidationError represents a validation failure with field context.
|
||
|
|
type ValidationError struct {
|
||
|
|
Field string
|
||
|
|
Message string
|
||
|
|
}
|
||
|
|
|
||
|
|
// Error implements the error interface.
|
||
|
|
func (e *ValidationError) Error() string {
|
||
|
|
return fmt.Sprintf("validation error [%s]: %s", e.Field, e.Message)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ValidateInputSize checks if the input telegram is within acceptable size limits.
|
||
|
|
// Returns ValidationError if the input is empty or exceeds MaxTelegramSize.
|
||
|
|
func ValidateInputSize(rawText string) error {
|
||
|
|
if len(rawText) == 0 {
|
||
|
|
return &ValidationError{
|
||
|
|
Field: "input",
|
||
|
|
Message: "empty input",
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(rawText) > MaxTelegramSize {
|
||
|
|
return &ValidationError{
|
||
|
|
Field: "input",
|
||
|
|
Message: fmt.Sprintf("input exceeds maximum size of %d characters (got %d)", MaxTelegramSize, len(rawText)),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ValidateBodySize checks if the body content is within acceptable size limits.
|
||
|
|
// Returns ValidationError if the body exceeds MaxBodySize.
|
||
|
|
func ValidateBodySize(body string) error {
|
||
|
|
if len(body) > MaxBodySize {
|
||
|
|
return &ValidationError{
|
||
|
|
Field: "body",
|
||
|
|
Message: fmt.Sprintf("body exceeds maximum size of %d characters (got %d)", MaxBodySize, len(body)),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// ValidateTokenCount checks if the token count is within reasonable limits.
|
||
|
|
// Returns ValidationError if token count exceeds MaxTokenCount.
|
||
|
|
func ValidateTokenCount(tokens []Token) error {
|
||
|
|
if len(tokens) > MaxTokenCount {
|
||
|
|
return &ValidationError{
|
||
|
|
Field: "tokens",
|
||
|
|
Message: fmt.Sprintf("token count exceeds maximum of %d (got %d)", MaxTokenCount, len(tokens)),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetRequiredField safely extracts a required field from parsed data.
|
||
|
|
// Returns ValidationError if the field doesn't exist or is empty.
|
||
|
|
func GetRequiredField(data map[string]string, field string) (string, error) {
|
||
|
|
value, exists := data[field]
|
||
|
|
if !exists {
|
||
|
|
return "", &ValidationError{
|
||
|
|
Field: field,
|
||
|
|
Message: fmt.Sprintf("required field '%s' not found in parsed data", field),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if value == "" {
|
||
|
|
return "", &ValidationError{
|
||
|
|
Field: field,
|
||
|
|
Message: fmt.Sprintf("required field '%s' is empty", field),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return value, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetOptionalField safely extracts an optional field from parsed data.
|
||
|
|
// Returns empty string if the field doesn't exist.
|
||
|
|
func GetOptionalField(data map[string]string, field string) string {
|
||
|
|
value, exists := data[field]
|
||
|
|
if !exists {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
return value
|
||
|
|
}
|
||
|
|
|
||
|
|
// SanitizeErrorForClient removes sensitive information from error messages
|
||
|
|
// before exposing them to external clients. This prevents leaking:
|
||
|
|
// - Raw telegram content (may contain sensitive flight data)
|
||
|
|
// - Internal implementation details
|
||
|
|
// - System paths or configuration
|
||
|
|
//
|
||
|
|
// The function preserves error type and general context while removing
|
||
|
|
// specific content that could be sensitive.
|
||
|
|
func SanitizeErrorForClient(err error) string {
|
||
|
|
if err == nil {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the error message string
|
||
|
|
errMsg := err.Error()
|
||
|
|
|
||
|
|
// Truncate long error messages that might contain sensitive content
|
||
|
|
// This applies to all error types, including ValidationError
|
||
|
|
if len(errMsg) > 200 {
|
||
|
|
return errMsg[:200] + "..."
|
||
|
|
}
|
||
|
|
|
||
|
|
return errMsg
|
||
|
|
}
|