Skip to main content

form_net/
io.rs

1//! Blocking readers: a pull-style API over `std::io::Read`, free of any
2//! runtime. Ask for the next part, read it like a file, ask for the next.
3
4use alloc::string::String;
5use alloc::vec::Vec;
6use core::fmt;
7use std::io::{self, Read};
8
9use crate::error::{EncodingError, FormError, Location};
10use crate::limits::{Limits, Policy};
11use crate::multipart::owned_head::OwnedPartHead;
12use crate::multipart::parser::{Event, MultipartParser, PartSummary};
13
14const READ_BUFFER: usize = 64 * 1024;
15
16/// Reads a multipart body from a blocking reader, one part at a time.
17///
18/// It has no hooks: the caller sees each part itself. Dropping a
19/// [`PartReader`] before its end skips the rest of the part at the next
20/// [`next_part`](Self::next_part).
21///
22/// # Examples
23///
24/// ```
25/// use std::io::Read;
26///
27/// let body = b"--X\r\nContent-Disposition: form-data; name=note\r\n\r\nhi\r\n--X\r\nContent-Disposition: form-data; name=f; filename=a.bin\r\n\r\n0123\r\n--X--";
28/// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
29/// let mut seen = Vec::new();
30/// while let Some(mut part) = reader.next_part()? {
31///     if part.head().view().is_file() {
32///         let mut bytes = Vec::new();
33///         part.read_to_end(&mut bytes).unwrap();
34///         seen.push(bytes.len());
35///     } else {
36///         seen.push(part.text()?.len());
37///     }
38/// }
39/// assert_eq!(seen, [2, 4]);
40/// # Ok::<(), form_net::FormError>(())
41/// ```
42pub struct MultipartReader<R: Read> {
43    reader: R,
44    parser: MultipartParser<Vec<u8>>,
45    buf: Vec<u8>,
46    /// The most of `buf` any read filled: only that is wiped.
47    buf_used: usize,
48    start: usize,
49    end: usize,
50    eof: bool,
51    head: OwnedPartHead,
52    pending: Vec<u8>,
53    pending_at: usize,
54    in_part: bool,
55    last: Option<PartSummary>,
56    done: bool,
57    /// Whether the `_charset_` value declared before the current part
58    /// lets its text be read: the parser's record, read before the part
59    /// started, as every other entry point reads it (D-128, D-141).
60    declared_ok: bool,
61    /// Bytes `save` has put on disk for this request.
62    #[cfg(feature = "fs")]
63    disk_used: u64,
64}
65
66impl<R: Read> Drop for MultipartReader<R> {
67    fn drop(&mut self) {
68        crate::wipe::wipe(self.buf.get_mut(..self.buf_used).unwrap_or(&mut []));
69        crate::wipe::wipe_vec(&mut self.pending);
70    }
71}
72
73impl<R: Read> fmt::Debug for MultipartReader<R> {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        f.debug_struct("MultipartReader")
76            .field("parser", &self.parser)
77            .field("in_part", &self.in_part)
78            .finish_non_exhaustive()
79    }
80}
81
82/// What the reader's loop produced.
83enum Got {
84    Start,
85    Data,
86    End(PartSummary),
87    Done,
88}
89
90impl<R: Read> MultipartReader<R> {
91    /// A reader with the default limits and policy.
92    ///
93    /// # Errors
94    ///
95    /// `UnsupportedMediaType` and the boundary errors.
96    pub fn new(content_type: &[u8], reader: R) -> Result<Self, FormError> {
97        Self::with_limits(content_type, reader, &Limits::DEFAULT, &Policy::DEFAULT)
98    }
99
100    /// A reader with explicit limits and policy.
101    ///
102    /// # Errors
103    ///
104    /// As [`new`](Self::new); `InvalidLimits`.
105    pub fn with_limits(
106        content_type: &[u8],
107        reader: R,
108        limits: &Limits,
109        policy: &Policy,
110    ) -> Result<Self, FormError> {
111        let boundary = crate::Boundary::parse(content_type)?;
112        let parser = MultipartParser::new(boundary, limits, policy)?;
113        Ok(MultipartReader {
114            reader,
115            parser,
116            buf: alloc::vec![0u8; READ_BUFFER],
117            buf_used: 0,
118            start: 0,
119            end: 0,
120            eof: false,
121            head: OwnedPartHead::with_capacity(limits.multipart_buffer_len(policy)),
122            pending: Vec::new(),
123            pending_at: 0,
124            in_part: false,
125            last: None,
126            done: false,
127            declared_ok: true,
128            #[cfg(feature = "fs")]
129            disk_used: 0,
130        })
131    }
132
133    /// The token field's value, once its part has ended.
134    #[must_use]
135    pub fn captured_token(&self) -> Option<&str> {
136        self.parser.captured_token()
137    }
138
139    fn fill(&mut self) -> Result<(), FormError> {
140        if self.start < self.end || self.eof {
141            return Ok(());
142        }
143        loop {
144            match self.reader.read(&mut self.buf) {
145                Ok(0) => {
146                    self.eof = true;
147                    self.start = 0;
148                    self.end = 0;
149                    return Ok(());
150                }
151                Ok(n) => {
152                    self.start = 0;
153                    self.end = n.min(self.buf.len());
154                    self.buf_used = self.buf_used.max(self.end);
155                    return Ok(());
156                }
157                Err(e) if e.kind() == io::ErrorKind::Interrupted => {
158                    // A failed read may have written anywhere in the buffer.
159                    self.buf_used = self.buf.len();
160                }
161                Err(e) => {
162                    self.buf_used = self.buf.len();
163                    return Err(FormError::Io { kind: e.kind() });
164                }
165            }
166        }
167    }
168
169    /// One parser event; data goes to `pending`.
170    fn step(&mut self) -> Result<Got, FormError> {
171        loop {
172            self.fill()?;
173            let input = self.buf.get(self.start..self.end).unwrap_or(&[]);
174            // Before `parse`: a `_charset_` part starting in this step resets
175            // the parser's record.
176            let declared_ok =
177                crate::multipart::parser::declared_readable(self.parser.declared_charset());
178            let step = self.parser.parse(input, self.eof)?;
179            self.start = self.start.saturating_add(step.consumed);
180            match step.event {
181                Event::PartStart(head) => {
182                    self.head.copy_from(&head);
183                    self.declared_ok = declared_ok;
184                    return Ok(Got::Start);
185                }
186                Event::Data(bytes) => {
187                    crate::wipe::wipe(&mut self.pending);
188                    self.pending.clear();
189                    crate::wipe::append_wiping(&mut self.pending, bytes, 4096, usize::MAX);
190                    self.pending_at = 0;
191                    return Ok(Got::Data);
192                }
193                Event::PartEnd(s) => return Ok(Got::End(s)),
194                Event::End => return Ok(Got::Done),
195                _ => {}
196            }
197        }
198    }
199
200    /// The next part, or `None` after the close delimiter. Skips whatever
201    /// is left of the previous part. After the close delimiter it reads the
202    /// rest of the body, which is epilogue and counts against
203    /// `max_epilogue_bytes` and `max_body_bytes`, as `parse_multipart`
204    /// counts it (D-142).
205    ///
206    /// # Errors
207    ///
208    /// Every multipart error; `Io { kind }` from the reader.
209    pub fn next_part(&mut self) -> Result<Option<PartReader<'_, R>>, FormError> {
210        if self.in_part {
211            self.parser.skip_part();
212            self.pending.clear();
213            while self.in_part {
214                if let Got::End(s) = self.step()? {
215                    self.end_part(s);
216                }
217            }
218        }
219        while !self.done {
220            match self.step()? {
221                Got::Start => {
222                    self.in_part = true;
223                    return Ok(Some(PartReader { inner: self }));
224                }
225                Got::Done => {
226                    self.done = true;
227                    self.drain_epilogue()?;
228                }
229                _ => {}
230            }
231        }
232        Ok(None)
233    }
234
235    /// Feeds the parser what follows the close delimiter, to the end of the
236    /// body, so the epilogue and body budgets hold.
237    fn drain_epilogue(&mut self) -> Result<(), FormError> {
238        loop {
239            self.fill()?;
240            // `fill` leaves the buffer empty only at the end of the body.
241            if self.start >= self.end {
242                return Ok(());
243            }
244            let input = self.buf.get(self.start..self.end).unwrap_or(&[]);
245            let step = self.parser.parse(input, self.eof)?;
246            if step.consumed == 0 {
247                return Ok(());
248            }
249            self.start = self.start.saturating_add(step.consumed);
250        }
251    }
252
253    fn end_part(&mut self, summary: PartSummary) {
254        self.in_part = false;
255        self.last = Some(summary);
256        self.pending.clear();
257    }
258}
259
260/// One part of a [`MultipartReader`]: read it like a file.
261///
262/// `Read` reports a parse error as `std::io::Error` with kind `InvalidData`
263/// and the `FormError` as its source.
264pub struct PartReader<'r, R: Read> {
265    inner: &'r mut MultipartReader<R>,
266}
267
268impl<R: Read> fmt::Debug for PartReader<'_, R> {
269    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270        f.debug_struct("PartReader")
271            .field("head", &self.inner.head)
272            .finish_non_exhaustive()
273    }
274}
275
276impl<R: Read> PartReader<'_, R> {
277    /// The part's head, copied when the part started.
278    #[must_use]
279    pub fn head(&self) -> &OwnedPartHead {
280        &self.inner.head
281    }
282
283    /// Reads the rest of the part and checks it as text (its charset, else
284    /// the `_charset_` field before it, else UTF-8), bounded by
285    /// `max_value_bytes` for file parts too.
286    ///
287    /// # Errors
288    ///
289    /// Every multipart error; `Encoding { InvalidUtf8 | UnsupportedCharset }`;
290    /// `Limit { ValueLength }`.
291    pub fn text(&mut self) -> Result<String, FormError> {
292        let own = self.inner.head.view().charset();
293        let cap = self.inner.parser.limits().value() as usize;
294        let mut out = Vec::new();
295        let read = (|| {
296            while let Some(chunk) = self.next_chunk()? {
297                if out.len().saturating_add(chunk.len()) > cap {
298                    return Err(FormError::limit(
299                        crate::Limit::ValueLength,
300                        Location::in_part(
301                            Some(self.inner.head.view().index()),
302                            self.inner.parser.bytes_seen(),
303                        ),
304                    ));
305                }
306                crate::wipe::append_wiping(&mut out, chunk, 4096, cap);
307            }
308            Ok(())
309        })();
310        if let Err(e) = read {
311            crate::wipe::wipe_vec(&mut out);
312            return Err(e);
313        }
314        let at = Location::in_part(
315            Some(self.inner.head.view().index()),
316            self.inner.parser.bytes_seen(),
317        );
318        if !own.readable(self.inner.declared_ok) {
319            crate::wipe::wipe_vec(&mut out);
320            return Err(FormError::encoding(EncodingError::UnsupportedCharset, at));
321        }
322        String::from_utf8(out).map_err(|e| {
323            let mut bytes = e.into_bytes();
324            crate::wipe::wipe_vec(&mut bytes);
325            FormError::encoding(EncodingError::InvalidUtf8, at)
326        })
327    }
328
329    /// Discards the rest of the part and returns its data length.
330    ///
331    /// # Errors
332    ///
333    /// Every multipart error.
334    pub fn skip(&mut self) -> Result<u64, FormError> {
335        self.inner.parser.skip_part();
336        self.inner.pending.clear();
337        while self.inner.in_part {
338            if let Got::End(s) = self.inner.step()? {
339                self.inner.end_part(s);
340            }
341        }
342        Ok(self.inner.last.map_or(0, |s| s.bytes))
343    }
344
345    /// Streams a file part into `store`.
346    ///
347    /// # Errors
348    ///
349    /// Every multipart error; `Io`, `Store`, `Limit { Disk }`.
350    #[cfg(feature = "fs")]
351    #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
352    pub fn save(&mut self, store: &crate::Store) -> Result<crate::StoredFile, FormError> {
353        use crate::hook::Sink;
354        // One request, one disk limit: the sink starts from what earlier
355        // saves of this body already put on disk.
356        let mut sink = store
357            .sink(self.inner.parser.limits())
358            .with_used_disk(self.inner.disk_used);
359        let head = self.inner.head.clone();
360        sink.open(&head.view())?;
361        let r = (|| {
362            while let Some(chunk) = self.next_chunk()? {
363                sink.write(chunk)?;
364            }
365            sink.close()
366        })();
367        if r.is_err() {
368            sink.abort();
369        } else {
370            self.inner.disk_used = sink.used_disk();
371        }
372        r
373    }
374
375    /// The next piece of data, or `None` at the end of the part.
376    fn next_chunk(&mut self) -> Result<Option<&[u8]>, FormError> {
377        let inner = &mut *self.inner;
378        if inner.pending_at < inner.pending.len() {
379            let chunk = inner.pending.get(inner.pending_at..).unwrap_or(&[]);
380            inner.pending_at = inner.pending.len();
381            return Ok(Some(chunk));
382        }
383        while inner.in_part {
384            match inner.step()? {
385                Got::Data => {
386                    inner.pending_at = inner.pending.len();
387                    return Ok(Some(&inner.pending));
388                }
389                Got::End(s) => inner.end_part(s),
390                _ => {}
391            }
392        }
393        Ok(None)
394    }
395}
396
397impl<R: Read> Read for PartReader<'_, R> {
398    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
399        let inner = &mut *self.inner;
400        loop {
401            if inner.pending_at < inner.pending.len() {
402                let src = inner.pending.get(inner.pending_at..).unwrap_or(&[]);
403                let n = src.len().min(out.len());
404                if let (Some(dst), Some(src)) = (out.get_mut(..n), src.get(..n)) {
405                    dst.copy_from_slice(src);
406                }
407                inner.pending_at = inner.pending_at.saturating_add(n);
408                return Ok(n);
409            }
410            if !inner.in_part {
411                return Ok(0);
412            }
413            match inner.step() {
414                Ok(Got::End(s)) => inner.end_part(s),
415                Ok(_) => {}
416                Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
417            }
418        }
419    }
420}