webdav_handler/
errors.rs

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