1use alloc::vec::Vec;
5use core::fmt;
6
7use crate::error::{FormError, Location};
8use crate::hook::{Inspector, Sink, Verdict};
9use crate::limits::EmptyFilePolicy;
10use crate::multipart::owned_head::OwnedPartHead;
11use crate::multipart::parser::{Event, MultipartParser, PartHead, PartKind, PartSummary};
12use crate::wipe::WipeVec;
13
14#[non_exhaustive]
17pub enum Progress<'d, F> {
18 Field {
20 name: &'d str,
22 value: &'d [u8],
24 },
25 File(F),
27 NeedInput,
29 End,
31}
32
33impl<F> fmt::Debug for Progress<'_, F> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Progress::Field { name, value } => f
37 .debug_struct("Field")
38 .field("name", name)
39 .field("value_len", &value.len())
40 .finish(),
41 Progress::File(_) => f.write_str("File(..)"),
42 Progress::NeedInput => f.write_str("NeedInput"),
43 Progress::End => f.write_str("End"),
44 }
45 }
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49enum Part {
50 Idle,
51 Field {
52 skip: bool,
53 },
54 File {
55 open: bool,
56 deferred: bool,
57 sniffing: bool,
58 skip: bool,
59 },
60}
61
62struct State<S> {
65 sink: S,
66 head: OwnedPartHead,
67 text: WipeVec,
68 sniff: WipeVec,
69 sniff_len: usize,
70 value_cap: usize,
71 skip_empty: bool,
72 part: Part,
73}
74
75#[derive(Clone, Copy, PartialEq, Eq)]
77enum Next {
78 Continue,
79 SkipPart,
80}
81
82fn refused(v: Verdict, at: Location) -> Result<bool, FormError> {
83 match v {
84 Verdict::Refuse(refusal) => Err(FormError::Refused { refusal, at }),
85 Verdict::Skip => Ok(true),
86 _ => Ok(false),
87 }
88}
89
90impl<S: Sink> State<S> {
91 fn start_file<I: Inspector>(
92 &mut self,
93 head: &PartHead<'_>,
94 inspector: &mut I,
95 at: Location,
96 ) -> Result<Next, FormError> {
97 if refused(inspector.part_start(head), at)? {
98 self.part = Part::File {
99 open: false,
100 deferred: false,
101 sniffing: false,
102 skip: true,
103 };
104 return Ok(Next::SkipPart);
105 }
106 crate::wipe::wipe(&mut self.sniff);
110 self.sniff.clear();
111 self.part = Part::File {
112 open: false,
113 deferred: false,
114 sniffing: self.sniff_len > 0,
115 skip: false,
116 };
117 Ok(Next::Continue)
118 }
119
120 fn on_start<I: Inspector>(
121 &mut self,
122 head: &PartHead<'_>,
123 inspector: &mut I,
124 at: Location,
125 ) -> Result<Next, FormError> {
126 self.head.copy_from(head);
127 match head.kind() {
128 PartKind::File => {
129 let empty = head.filename().is_some_and(|f| f.is_empty());
130 if empty && self.skip_empty {
131 self.part = Part::File {
132 open: false,
133 deferred: true,
134 sniffing: false,
135 skip: false,
136 };
137 return Ok(Next::Continue);
138 }
139 self.start_file(head, inspector, at)
140 }
141 _ => {
142 crate::wipe::wipe(&mut self.text);
143 self.text.clear();
144 if refused(inspector.part_start(head), at)? {
145 self.part = Part::Field { skip: true };
146 return Ok(Next::SkipPart);
147 }
148 self.part = Part::Field { skip: false };
149 Ok(Next::Continue)
150 }
151 }
152 }
153
154 fn ensure_open(&mut self) -> Result<(), FormError> {
156 if let Part::File { open: false, .. } = self.part {
157 self.sink.open(&self.head.view())?;
158 if let Part::File { open, .. } = &mut self.part {
159 *open = true;
160 }
161 }
162 Ok(())
163 }
164
165 fn skip_file(&mut self) {
167 if let Part::File { open: true, .. } = self.part {
168 self.sink.abort();
169 }
170 self.part = Part::File {
171 open: false,
172 deferred: false,
173 sniffing: false,
174 skip: true,
175 };
176 }
177
178 fn file_bytes<I: Inspector>(
180 &mut self,
181 index: u32,
182 bytes: &[u8],
183 inspector: &mut I,
184 at: Location,
185 ) -> Result<Next, FormError> {
186 if bytes.is_empty() {
187 return Ok(Next::Continue);
188 }
189 if refused(inspector.data(index, bytes), at)? {
190 self.skip_file();
191 return Ok(Next::SkipPart);
192 }
193 self.ensure_open()?;
194 self.sink.write(bytes).map(|()| Next::Continue)
195 }
196
197 fn flush_sniff<I: Inspector>(
199 &mut self,
200 index: u32,
201 inspector: &mut I,
202 at: Location,
203 ) -> Result<Next, FormError> {
204 if let Part::File { sniffing, .. } = &mut self.part {
205 *sniffing = false;
206 }
207 let window = core::mem::take(&mut self.sniff);
208 let verdict = inspector.sniff(&self.head.view(), &window);
209 let result = match refused(verdict, at) {
210 Err(e) => Err(e),
211 Ok(true) => {
212 self.skip_file();
213 Ok(Next::SkipPart)
214 }
215 Ok(false) => self.file_bytes(index, &window, inspector, at),
216 };
217 self.sniff = window;
218 crate::wipe::wipe(&mut self.sniff);
219 self.sniff.clear();
220 result
221 }
222
223 fn on_data<I: Inspector>(
224 &mut self,
225 bytes: &[u8],
226 inspector: &mut I,
227 at: Location,
228 ) -> Result<Next, FormError> {
229 let index = self.head.view().index();
230 match self.part {
231 Part::Field { skip: false } => {
232 if refused(inspector.data(index, bytes), at)? {
233 self.part = Part::Field { skip: true };
234 return Ok(Next::SkipPart);
235 }
236 crate::wipe::append_wiping(&mut self.text, bytes, 64 * 1024, self.value_cap);
237 Ok(Next::Continue)
238 }
239 Part::File { deferred: true, .. } => {
240 let head = self.head.clone();
241 if self.start_file(&head.view(), inspector, at)? == Next::SkipPart {
242 return Ok(Next::SkipPart);
243 }
244 self.on_data(bytes, inspector, at)
245 }
246 Part::File {
247 skip: false,
248 sniffing: true,
249 ..
250 } => {
251 let room = self.sniff_len.saturating_sub(self.sniff.len());
252 let (head, rest) = bytes.split_at(room.min(bytes.len()));
253 self.sniff.extend_from_slice(head);
254 if self.sniff.len() < self.sniff_len {
255 return Ok(Next::Continue);
256 }
257 if self.flush_sniff(index, inspector, at)? == Next::SkipPart {
258 return Ok(Next::SkipPart);
259 }
260 self.file_bytes(index, rest, inspector, at)
261 }
262 Part::File { skip: false, .. } => self.file_bytes(index, bytes, inspector, at),
263 _ => Ok(Next::Continue),
264 }
265 }
266}
267
268enum Done<F> {
270 Field,
271 File(F),
272 NeedInput,
273 End,
274}
275
276pub struct Driver<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> {
298 parser: MultipartParser<B>,
299 state: State<S>,
300 ended: bool,
301 failed: bool,
302}
303
304impl<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> fmt::Debug for Driver<B, S> {
305 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306 f.debug_struct("Driver")
307 .field("parser", &self.parser)
308 .field("ended", &self.ended)
309 .finish_non_exhaustive()
310 }
311}
312
313impl<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> Driver<B, S> {
314 #[must_use]
316 pub fn new(parser: MultipartParser<B>, sink: S) -> Self {
317 let limits = *parser.limits();
318 let policy = *parser.policy();
319 let sniff_len = limits.sniff() as usize;
320 Driver {
321 state: State {
322 sink,
323 head: OwnedPartHead::with_capacity(limits.multipart_buffer_len(&policy)),
324 text: WipeVec::default(),
325 sniff: WipeVec(Vec::with_capacity(sniff_len)),
326 sniff_len,
327 value_cap: limits.value() as usize,
328 skip_empty: policy.empty_files == EmptyFilePolicy::Skip,
329 part: Part::Idle,
330 },
331 parser,
332 ended: false,
333 failed: false,
334 }
335 }
336
337 #[must_use]
339 pub const fn parser(&self) -> &MultipartParser<B> {
340 &self.parser
341 }
342
343 pub fn into_parts(self) -> (MultipartParser<B>, S) {
345 (self.parser, self.state.sink)
346 }
347
348 pub fn push<'d, I: Inspector>(
358 &'d mut self,
359 input: &[u8],
360 eof: bool,
361 inspector: &mut I,
362 ) -> Result<(usize, Progress<'d, S::Output>), FormError> {
363 if self.failed {
364 return Err(FormError::Poisoned);
365 }
366 match self.run(input, eof, inspector) {
367 Ok((consumed, done)) => Ok((
368 consumed,
369 match done {
370 Done::Field => Progress::Field {
371 name: self.state.head_name(),
372 value: &self.state.text,
373 },
374 Done::File(f) => Progress::File(f),
375 Done::NeedInput => Progress::NeedInput,
376 Done::End => Progress::End,
377 },
378 )),
379 Err(e) => {
380 self.failed = true;
381 self.state.sink.abort();
382 inspector.failed(&e);
383 Err(e)
384 }
385 }
386 }
387
388 fn at(&self) -> Location {
389 Location::in_part(
390 self.parser.parts_seen().checked_sub(1),
391 self.parser.bytes_seen(),
392 )
393 }
394
395 fn run<I: Inspector>(
396 &mut self,
397 input: &[u8],
398 eof: bool,
399 inspector: &mut I,
400 ) -> Result<(usize, Done<S::Output>), FormError> {
401 let mut pos = 0usize;
402 loop {
403 let rest = input.get(pos..).unwrap_or(&[]);
404 let seen = self.parser.bytes_seen();
405 let parts = self.parser.parts_seen();
406 let step = self.parser.parse(rest, eof)?;
407 pos = pos.saturating_add(step.consumed);
408 let index = match &step.event {
409 Event::PartStart(head) => Some(head.index()),
410 _ => parts.checked_sub(1),
411 };
412 let at = Location::in_part(index, seen.saturating_add(step.consumed as u64));
413 let next = match step.event {
414 Event::PartStart(head) => self.state.on_start(&head, inspector, at)?,
415 Event::Data(bytes) => self.state.on_data(bytes, inspector, at)?,
416 Event::PartEnd(summary) => {
417 if let Some(done) = self.on_end(summary, inspector)? {
418 return Ok((pos, done));
419 }
420 Next::Continue
421 }
422 Event::End => {
423 if !self.ended {
424 self.ended = true;
425 if let Verdict::Refuse(refusal) = inspector.end() {
426 return Err(FormError::Refused { refusal, at });
427 }
428 }
429 return Ok((pos, Done::End));
430 }
431 _ => return Ok((pos, Done::NeedInput)),
432 };
433 if next == Next::SkipPart {
434 self.parser.skip_part();
435 }
436 }
437 }
438
439 fn on_end<I: Inspector>(
440 &mut self,
441 summary: PartSummary,
442 inspector: &mut I,
443 ) -> Result<Option<Done<S::Output>>, FormError> {
444 let at = self.at();
445 let part = core::mem::replace(&mut self.state.part, Part::Idle);
446 let skipped = summary.skipped
447 || matches!(
448 part,
449 Part::Field { skip: true } | Part::File { skip: true, .. }
450 );
451 let summary = PartSummary { skipped, ..summary };
452 match part {
453 Part::File { deferred: true, .. } => Ok(None),
454 Part::File {
455 skip: false,
456 sniffing,
457 ..
458 } => {
459 self.state.part = part;
462 let flushed = if sniffing {
463 self.state.flush_sniff(summary.index, inspector, at)
464 } else {
465 Ok(Next::Continue)
466 };
467 let opened = match flushed {
468 Ok(Next::Continue) => self.state.ensure_open().map(|()| true),
469 Ok(Next::SkipPart) => Ok(false),
470 Err(e) => Err(e),
471 };
472 self.state.part = Part::Idle;
473 if !opened? {
474 let summary = PartSummary {
475 skipped: true,
476 ..summary
477 };
478 refused(inspector.part_end(&summary), at)?;
479 return Ok(None);
480 }
481 let output = self.state.sink.close()?;
482 refused(inspector.part_end(&summary), at)?;
483 Ok(Some(Done::File(output)))
484 }
485 Part::Field { skip: false } => {
486 let name = self.state.head.view().name();
487 let skip = refused(inspector.field(name, &self.state.text), at)?;
490 let summary = PartSummary {
491 skipped: skip,
492 ..summary
493 };
494 refused(inspector.part_end(&summary), at)?;
495 if skip {
496 crate::wipe::wipe(&mut self.state.text);
497 return Ok(None);
498 }
499 Ok(Some(Done::Field))
500 }
501 _ => {
502 refused(inspector.part_end(&summary), at)?;
503 Ok(None)
504 }
505 }
506 }
507}
508
509impl<S> State<S> {
510 fn head_name(&self) -> &str {
511 self.head.view().name()
512 }
513}
514
515impl<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> Driver<B, S> {
516 #[cfg(feature = "fs")]
518 pub(crate) const fn has_failed(&self) -> bool {
519 self.failed
520 }
521
522 #[cfg(feature = "fs")]
524 pub(crate) fn current_head_charset(&self) -> crate::multipart::parser::Charset {
525 self.state.head.view().charset()
526 }
527}