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::{MultipartEvent, 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: crate::multipart::parser::TextRule,
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    ///
97    /// # Examples
98    ///
99    /// ```
100    /// let body = b"--X\r\nContent-Disposition: form-data; name=note\r\n\r\nhi\r\n--X--";
101    /// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
102    /// let mut part = reader.next_part()?.unwrap();
103    /// assert_eq!(part.text()?, "hi");
104    /// # Ok::<(), form_net::FormError>(())
105    /// ```
106    pub fn new(content_type: &[u8], reader: R) -> Result<Self, FormError> {
107        Self::with_limits(content_type, reader, &Limits::DEFAULT, &Policy::DEFAULT)
108    }
109
110    /// A reader with explicit limits and policy.
111    ///
112    /// # Errors
113    ///
114    /// As [`new`](Self::new); `InvalidLimits`.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use form_net::{Limits, MultipartReader, Policy};
120    ///
121    /// let limits = Limits::DEFAULT.with_max_value_bytes(4);
122    /// let body = b"--X\r\nContent-Disposition: form-data; name=note\r\n\r\ntoo long\r\n--X--";
123    /// let ct = b"multipart/form-data; boundary=X";
124    /// let mut reader = MultipartReader::with_limits(ct, &body[..], &limits, &Policy::DEFAULT)?;
125    /// let mut part = reader.next_part()?.unwrap();
126    /// assert_eq!(part.text().unwrap_err().code(), "limit.value_length");
127    /// # Ok::<(), form_net::FormError>(())
128    /// ```
129    pub fn with_limits(
130        content_type: &[u8],
131        reader: R,
132        limits: &Limits,
133        policy: &Policy,
134    ) -> Result<Self, FormError> {
135        let boundary = crate::Boundary::parse(content_type)?;
136        let parser = MultipartParser::new(boundary, limits, policy)?;
137        Ok(MultipartReader {
138            reader,
139            parser,
140            buf: alloc::vec![0u8; READ_BUFFER],
141            buf_used: 0,
142            start: 0,
143            end: 0,
144            eof: false,
145            head: OwnedPartHead::with_capacity(limits.multipart_buffer_len(policy)),
146            pending: Vec::new(),
147            pending_at: 0,
148            in_part: false,
149            last: None,
150            done: false,
151            declared: crate::multipart::parser::TextRule::Utf8,
152            #[cfg(feature = "fs")]
153            disk_used: 0,
154        })
155    }
156
157    /// The token field's value, once its part has ended.
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// use form_net::{Limits, MultipartReader, Policy, TokenField};
163    ///
164    /// let policy = Policy::DEFAULT.with_token_field(TokenField::new("csrf"));
165    /// let body = b"--X\r\nContent-Disposition: form-data; name=csrf\r\n\r\nt0k3n\r\n--X--";
166    /// let ct = b"multipart/form-data; boundary=X";
167    /// let mut reader = MultipartReader::with_limits(ct, &body[..], &Limits::DEFAULT, &policy)?;
168    /// while let Some(mut part) = reader.next_part()? {
169    ///     part.skip()?;
170    /// }
171    /// assert_eq!(reader.captured_token(), Some("t0k3n"));
172    /// # Ok::<(), form_net::FormError>(())
173    /// ```
174    #[must_use]
175    pub fn captured_token(&self) -> Option<&str> {
176        self.parser.captured_token()
177    }
178
179    fn fill(&mut self) -> Result<(), FormError> {
180        if self.start < self.end || self.eof {
181            return Ok(());
182        }
183        loop {
184            match self.reader.read(&mut self.buf) {
185                Ok(0) => {
186                    self.eof = true;
187                    self.start = 0;
188                    self.end = 0;
189                    return Ok(());
190                }
191                Ok(n) => {
192                    self.start = 0;
193                    self.end = n.min(self.buf.len());
194                    self.buf_used = self.buf_used.max(self.end);
195                    return Ok(());
196                }
197                Err(e) if e.kind() == io::ErrorKind::Interrupted => {
198                    // A failed read may have written anywhere in the buffer.
199                    self.buf_used = self.buf.len();
200                }
201                Err(e) => {
202                    self.buf_used = self.buf.len();
203                    return Err(FormError::BodyRead { kind: e.kind() });
204                }
205            }
206        }
207    }
208
209    /// One parser event; data goes to `pending`.
210    fn step(&mut self) -> Result<Got, FormError> {
211        loop {
212            self.fill()?;
213            let input = self.buf.get(self.start..self.end).unwrap_or(&[]);
214            // Before `parse`: a `_charset_` part starting in this step resets
215            // the parser's record.
216            let declared = crate::multipart::parser::declared_rule(self.parser.declared_charset());
217            let step = self.parser.parse(input, self.eof)?;
218            self.start = self.start.saturating_add(step.consumed);
219            match step.event {
220                MultipartEvent::PartStart(head) => {
221                    self.head.copy_from(&head);
222                    self.declared = declared;
223                    return Ok(Got::Start);
224                }
225                MultipartEvent::Data(bytes) => {
226                    crate::wipe::wipe(&mut self.pending);
227                    self.pending.clear();
228                    crate::wipe::append_wiping(&mut self.pending, bytes, 4096, usize::MAX);
229                    self.pending_at = 0;
230                    return Ok(Got::Data);
231                }
232                MultipartEvent::PartEnd(s) => return Ok(Got::End(s)),
233                MultipartEvent::End => return Ok(Got::Done),
234                _ => {}
235            }
236        }
237    }
238
239    /// The next part, or `None` after the close delimiter. Skips whatever
240    /// is left of the previous part. After the close delimiter it reads the
241    /// rest of the body, which is epilogue and counts against
242    /// `max_epilogue_bytes` and `max_body_bytes`, as `parse_multipart`
243    /// counts it (D-142).
244    ///
245    /// # Errors
246    ///
247    /// Every multipart error; `Io { kind }` from the reader.
248    ///
249    /// # Examples
250    ///
251    /// ```
252    /// let body = b"--X\r\nContent-Disposition: form-data; name=a\r\n\r\n1\r\n--X\r\nContent-Disposition: form-data; name=b\r\n\r\n2\r\n--X--";
253    /// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
254    /// let mut names = Vec::new();
255    /// while let Some(part) = reader.next_part()? {
256    ///     names.push(part.head().view().name().to_owned());
257    /// }
258    /// assert_eq!(names, ["a", "b"]);
259    /// # Ok::<(), form_net::FormError>(())
260    /// ```
261    pub fn next_part(&mut self) -> Result<Option<PartReader<'_, R>>, FormError> {
262        if self.in_part {
263            self.parser.skip_part();
264            self.pending.clear();
265            while self.in_part {
266                if let Got::End(s) = self.step()? {
267                    self.end_part(s);
268                }
269            }
270        }
271        while !self.done {
272            match self.step()? {
273                Got::Start => {
274                    self.in_part = true;
275                    return Ok(Some(PartReader { inner: self }));
276                }
277                Got::Done => {
278                    self.done = true;
279                    self.drain_epilogue()?;
280                }
281                _ => {}
282            }
283        }
284        Ok(None)
285    }
286
287    /// Feeds the parser what follows the close delimiter, to the end of the
288    /// body, so the epilogue and body budgets hold.
289    fn drain_epilogue(&mut self) -> Result<(), FormError> {
290        loop {
291            self.fill()?;
292            // `fill` leaves the buffer empty only at the end of the body.
293            if self.start >= self.end {
294                return Ok(());
295            }
296            let input = self.buf.get(self.start..self.end).unwrap_or(&[]);
297            let step = self.parser.parse(input, self.eof)?;
298            if step.consumed == 0 {
299                return Ok(());
300            }
301            self.start = self.start.saturating_add(step.consumed);
302        }
303    }
304
305    fn end_part(&mut self, summary: PartSummary) {
306        self.in_part = false;
307        self.last = Some(summary);
308        self.pending.clear();
309    }
310}
311
312/// One part of a [`MultipartReader`]: read it like a file.
313///
314/// `Read` reports a parse error as `std::io::Error` with kind `InvalidData`
315/// and the `FormError` as its source.
316///
317/// # Examples
318///
319/// ```
320/// use std::io::Read;
321///
322/// let body = b"--X\r\nContent-Disposition: form-data; name=f; filename=a.bin\r\n\r\n0123\r\n--X--";
323/// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
324/// let mut part = reader.next_part()?.unwrap();
325/// let mut bytes = Vec::new();
326/// part.read_to_end(&mut bytes)?;
327/// assert_eq!(bytes, b"0123");
328/// # Ok::<(), Box<dyn std::error::Error>>(())
329/// ```
330pub struct PartReader<'r, R: Read> {
331    inner: &'r mut MultipartReader<R>,
332}
333
334impl<R: Read> fmt::Debug for PartReader<'_, R> {
335    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336        f.debug_struct("PartReader")
337            .field("head", &self.inner.head)
338            .finish_non_exhaustive()
339    }
340}
341
342impl<R: Read> PartReader<'_, R> {
343    /// The part's head, copied when the part started.
344    ///
345    /// # Examples
346    ///
347    /// ```
348    /// let body = b"--X\r\nContent-Disposition: form-data; name=f; filename=a.txt\r\n\r\nhi\r\n--X--";
349    /// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
350    /// let part = reader.next_part()?.unwrap();
351    /// let head = part.head().view();
352    /// assert_eq!((head.name(), head.is_file()), ("f", true));
353    /// # Ok::<(), form_net::FormError>(())
354    /// ```
355    #[must_use]
356    pub fn head(&self) -> &OwnedPartHead {
357        &self.inner.head
358    }
359
360    /// Reads the rest of the part and checks it as text (its charset, else
361    /// the `_charset_` field before it, else UTF-8), bounded by
362    /// `max_value_bytes` for file parts too.
363    ///
364    /// # Errors
365    ///
366    /// Every multipart error; `Encoding { InvalidUtf8 | UnsupportedCharset }`;
367    /// `Limit { ValueLength }`.
368    ///
369    /// # Examples
370    ///
371    /// ```
372    /// let body = b"--X\r\nContent-Disposition: form-data; name=title\r\n\r\nHoliday\r\n--X--";
373    /// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
374    /// let mut part = reader.next_part()?.unwrap();
375    /// assert_eq!(part.text()?, "Holiday");
376    /// # Ok::<(), form_net::FormError>(())
377    /// ```
378    pub fn text(&mut self) -> Result<String, FormError> {
379        let own = self.inner.head.view().charset();
380        let cap = self.inner.parser.limits().value() as usize;
381        let mut out = Vec::new();
382        let read = (|| {
383            while let Some(chunk) = self.next_chunk()? {
384                if out.len().saturating_add(chunk.len()) > cap {
385                    return Err(FormError::limit(
386                        crate::Limit::ValueLength,
387                        Location::in_part(
388                            Some(self.inner.head.view().index()),
389                            self.inner.parser.bytes_seen(),
390                        ),
391                    ));
392                }
393                crate::wipe::append_wiping(&mut out, chunk, 4096, cap);
394            }
395            Ok(())
396        })();
397        if let Err(e) = read {
398            crate::wipe::wipe_vec(&mut out);
399            return Err(e);
400        }
401        let at = Location::in_part(
402            Some(self.inner.head.view().index()),
403            self.inner.parser.bytes_seen(),
404        );
405        if let Err(reason) = own.rule(self.inner.declared).check(&out) {
406            crate::wipe::wipe_vec(&mut out);
407            return Err(FormError::encoding(reason, at));
408        }
409        String::from_utf8(out).map_err(|e| {
410            let mut bytes = e.into_bytes();
411            crate::wipe::wipe_vec(&mut bytes);
412            FormError::encoding(EncodingError::InvalidUtf8, at)
413        })
414    }
415
416    /// Discards the rest of the part and returns its data length.
417    ///
418    /// # Errors
419    ///
420    /// Every multipart error.
421    ///
422    /// # Examples
423    ///
424    /// ```
425    /// let body = b"--X\r\nContent-Disposition: form-data; name=f; filename=a.bin\r\n\r\n0123\r\n--X--";
426    /// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
427    /// let mut part = reader.next_part()?.unwrap();
428    /// assert_eq!(part.skip()?, 4);
429    /// assert!(reader.next_part()?.is_none());
430    /// # Ok::<(), form_net::FormError>(())
431    /// ```
432    pub fn skip(&mut self) -> Result<u64, FormError> {
433        self.inner.parser.skip_part();
434        self.inner.pending.clear();
435        while self.inner.in_part {
436            if let Got::End(s) = self.inner.step()? {
437                self.inner.end_part(s);
438            }
439        }
440        Ok(self.inner.last.map_or(0, |s| s.bytes))
441    }
442
443    /// Streams a file part into `store`.
444    ///
445    /// # Errors
446    ///
447    /// Every multipart error; `Io`, `Store`, `Limit { Disk }`.
448    ///
449    /// # Examples
450    ///
451    /// ```
452    /// // A memory-only store keeps the file off the file system.
453    /// let store = form_net::Store::memory_only();
454    /// let body = b"--X\r\nContent-Disposition: form-data; name=f; filename=a.txt\r\n\r\nhello\r\n--X--";
455    /// let mut reader = form_net::MultipartReader::new(b"multipart/form-data; boundary=X", &body[..])?;
456    /// let file = reader.next_part()?.unwrap().save(&store)?;
457    /// assert_eq!(file.bytes(), Some(&b"hello"[..]));
458    /// # Ok::<(), form_net::FormError>(())
459    /// ```
460    #[cfg(feature = "fs")]
461    #[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
462    pub fn save(&mut self, store: &crate::Store) -> Result<crate::StoredFile, FormError> {
463        use crate::hook::Sink;
464        // One request, one disk limit: the sink starts from what earlier
465        // saves of this body already put on disk.
466        let mut sink = store
467            .sink(self.inner.parser.limits())
468            .with_used_disk(self.inner.disk_used);
469        let head = self.inner.head.clone();
470        sink.open(&head.view())?;
471        let r = (|| {
472            while let Some(chunk) = self.next_chunk()? {
473                sink.write(chunk)?;
474            }
475            sink.close()
476        })();
477        if r.is_err() {
478            sink.abort();
479        } else {
480            self.inner.disk_used = sink.used_disk();
481        }
482        r
483    }
484
485    /// The next piece of data, or `None` at the end of the part.
486    fn next_chunk(&mut self) -> Result<Option<&[u8]>, FormError> {
487        let inner = &mut *self.inner;
488        if inner.pending_at < inner.pending.len() {
489            let chunk = inner.pending.get(inner.pending_at..).unwrap_or(&[]);
490            inner.pending_at = inner.pending.len();
491            return Ok(Some(chunk));
492        }
493        while inner.in_part {
494            match inner.step()? {
495                Got::Data => {
496                    inner.pending_at = inner.pending.len();
497                    return Ok(Some(&inner.pending));
498                }
499                Got::End(s) => inner.end_part(s),
500                _ => {}
501            }
502        }
503        Ok(None)
504    }
505}
506
507impl<R: Read> Read for PartReader<'_, R> {
508    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
509        let inner = &mut *self.inner;
510        loop {
511            if inner.pending_at < inner.pending.len() {
512                let src = inner.pending.get(inner.pending_at..).unwrap_or(&[]);
513                let n = src.len().min(out.len());
514                if let (Some(dst), Some(src)) = (out.get_mut(..n), src.get(..n)) {
515                    dst.copy_from_slice(src);
516                }
517                inner.pending_at = inner.pending_at.saturating_add(n);
518                return Ok(n);
519            }
520            if !inner.in_part {
521                return Ok(0);
522            }
523            match inner.step() {
524                Ok(Got::End(s)) => inner.end_part(s),
525                Ok(_) => {}
526                Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
527            }
528        }
529    }
530}