dav_server/
errors.rs

1use std::error::Error;
2use std::io::{self, ErrorKind};
3
4use http::StatusCode;
5
6use crate::fs::FsError;
7
8pub(crate) type DavResult<T> = Result<T, DavError>;
9
10#[derive(Debug)]
11pub(crate) enum DavError {
12    XmlReadError,  // error reading/parsing xml
13    XmlParseError, // error interpreting xml
14    InvalidPath,   // error parsing path
15    IllegalPath,   // path not valid here
16    ForbiddenPath, // too many dotdots
17    UnknownDavMethod,
18    ChanError,
19    Utf8Error,
20    Status(StatusCode),
21    StatusClose(StatusCode),
22    FsError(FsError),
23    IoError(io::Error),
24    XmlReaderError(xml::reader::Error),
25    XmlWriterError(xml::writer::Error),
26}
27
28impl Error for DavError {
29    fn description(&self) -> &str {
30        "DAV error"
31    }
32
33    fn cause(&self) -> Option<&dyn Error> {
34        match *self {
35            DavError::FsError(ref e) => Some(e),
36            DavError::IoError(ref e) => Some(e),
37            DavError::XmlReaderError(ref e) => Some(e),
38            DavError::XmlWriterError(ref e) => Some(e),
39            _ => None,
40        }
41    }
42}
43
44impl std::fmt::Display for DavError {
45    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46        match *self {
47            DavError::XmlReaderError(_) => write!(f, "XML parse error"),
48            DavError::XmlWriterError(_) => write!(f, "XML generate error"),
49            DavError::IoError(_) => write!(f, "I/O error"),
50            _ => write!(f, "{:?}", self),
51        }
52    }
53}
54
55impl From<FsError> for DavError {
56    fn from(e: FsError) -> Self {
57        DavError::FsError(e)
58    }
59}
60
61impl From<DavError> for io::Error {
62    fn from(e: DavError) -> Self {
63        match e {
64            DavError::IoError(e) => e,
65            DavError::FsError(e) => e.into(),
66            _ => io::Error::new(io::ErrorKind::Other, e),
67        }
68    }
69}
70
71impl From<FsError> for io::Error {
72    fn from(e: FsError) -> Self {
73        fserror_to_ioerror(e)
74    }
75}
76
77impl From<io::Error> for DavError {
78    fn from(e: io::Error) -> Self {
79        DavError::IoError(e)
80    }
81}
82
83impl From<StatusCode> for DavError {
84    fn from(e: StatusCode) -> Self {
85        DavError::Status(e)
86    }
87}
88
89impl From<xml::reader::Error> for DavError {
90    fn from(e: xml::reader::Error) -> Self {
91        DavError::XmlReaderError(e)
92    }
93}
94
95impl From<xml::writer::Error> for DavError {
96    fn from(e: xml::writer::Error) -> Self {
97        DavError::XmlWriterError(e)
98    }
99}
100
101impl From<std::str::Utf8Error> for DavError {
102    fn from(_: std::str::Utf8Error) -> Self {
103        DavError::Utf8Error
104    }
105}
106
107impl From<std::string::FromUtf8Error> for DavError {
108    fn from(_: std::string::FromUtf8Error) -> Self {
109        DavError::Utf8Error
110    }
111}
112
113impl From<futures_channel::mpsc::SendError> for DavError {
114    fn from(_e: futures_channel::mpsc::SendError) -> Self {
115        DavError::ChanError
116    }
117}
118
119fn fserror_to_ioerror(e: FsError) -> io::Error {
120    match e {
121        FsError::NotImplemented => io::Error::new(io::ErrorKind::Other, "NotImplemented"),
122        FsError::GeneralFailure => io::Error::new(io::ErrorKind::Other, "GeneralFailure"),
123        FsError::Exists => io::Error::new(io::ErrorKind::AlreadyExists, "Exists"),
124        FsError::NotFound => io::Error::new(io::ErrorKind::NotFound, "Notfound"),
125        FsError::Forbidden => io::Error::new(io::ErrorKind::PermissionDenied, "Forbidden"),
126        FsError::InsufficientStorage => io::Error::new(io::ErrorKind::Other, "InsufficientStorage"),
127        FsError::LoopDetected => io::Error::new(io::ErrorKind::Other, "LoopDetected"),
128        FsError::PathTooLong => io::Error::new(io::ErrorKind::Other, "PathTooLong"),
129        FsError::TooLarge => io::Error::new(io::ErrorKind::Other, "TooLarge"),
130        FsError::IsRemote => io::Error::new(io::ErrorKind::Other, "IsRemote"),
131    }
132}
133
134fn ioerror_to_status(ioerror: &io::Error) -> StatusCode {
135    match ioerror.kind() {
136        ErrorKind::NotFound => StatusCode::NOT_FOUND,
137        ErrorKind::PermissionDenied => StatusCode::FORBIDDEN,
138        ErrorKind::AlreadyExists => StatusCode::CONFLICT,
139        ErrorKind::TimedOut => StatusCode::GATEWAY_TIMEOUT,
140        _ => StatusCode::BAD_GATEWAY,
141    }
142}
143
144fn fserror_to_status(e: &FsError) -> StatusCode {
145    match e {
146        FsError::NotImplemented => StatusCode::NOT_IMPLEMENTED,
147        FsError::GeneralFailure => StatusCode::INTERNAL_SERVER_ERROR,
148        FsError::Exists => StatusCode::METHOD_NOT_ALLOWED,
149        FsError::NotFound => StatusCode::NOT_FOUND,
150        FsError::Forbidden => StatusCode::FORBIDDEN,
151        FsError::InsufficientStorage => StatusCode::INSUFFICIENT_STORAGE,
152        FsError::LoopDetected => StatusCode::LOOP_DETECTED,
153        FsError::PathTooLong => StatusCode::URI_TOO_LONG,
154        FsError::TooLarge => StatusCode::PAYLOAD_TOO_LARGE,
155        FsError::IsRemote => StatusCode::BAD_GATEWAY,
156    }
157}
158
159impl DavError {
160    pub(crate) fn statuscode(&self) -> StatusCode {
161        match *self {
162            DavError::XmlReadError => StatusCode::BAD_REQUEST,
163            DavError::XmlParseError => StatusCode::BAD_REQUEST,
164            DavError::InvalidPath => StatusCode::BAD_REQUEST,
165            DavError::IllegalPath => StatusCode::BAD_GATEWAY,
166            DavError::ForbiddenPath => StatusCode::FORBIDDEN,
167            DavError::UnknownDavMethod => StatusCode::NOT_IMPLEMENTED,
168            DavError::ChanError => StatusCode::INTERNAL_SERVER_ERROR,
169            DavError::Utf8Error => StatusCode::UNSUPPORTED_MEDIA_TYPE,
170            DavError::IoError(ref e) => ioerror_to_status(e),
171            DavError::FsError(ref e) => fserror_to_status(e),
172            DavError::Status(e) => e,
173            DavError::StatusClose(e) => e,
174            DavError::XmlReaderError(ref _e) => StatusCode::BAD_REQUEST,
175            DavError::XmlWriterError(ref _e) => StatusCode::INTERNAL_SERVER_ERROR,
176        }
177    }
178
179    pub(crate) fn must_close(&self) -> bool {
180        !matches!(
181            self,
182            &DavError::Status(_)
183                | &DavError::FsError(FsError::NotFound)
184                | &DavError::FsError(FsError::Forbidden)
185                | &DavError::FsError(FsError::Exists)
186        )
187    }
188}