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::{
12 MultipartEvent, MultipartParser, PartHead, PartKind, PartSummary, TextRule,
13};
14use crate::wipe::WipeVec;
15
16#[non_exhaustive]
40pub enum Progress<'d, F> {
41 Field {
43 name: &'d str,
45 value: &'d [u8],
47 },
48 File(F),
50 NeedInput,
52 End,
54}
55
56impl<F> fmt::Debug for Progress<'_, F> {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 Progress::Field { name, value } => f
60 .debug_struct("Field")
61 .field("name", name)
62 .field("value_len", &value.len())
63 .finish(),
64 Progress::File(_) => f.write_str("File(..)"),
65 Progress::NeedInput => f.write_str("NeedInput"),
66 Progress::End => f.write_str("End"),
67 }
68 }
69}
70
71#[derive(Clone, Copy, Debug, PartialEq, Eq)]
72enum Part {
73 Idle,
74 Field {
75 skip: bool,
76 rule: TextRule,
79 },
80 File {
81 open: bool,
82 deferred: bool,
83 sniffing: bool,
84 skip: bool,
85 },
86}
87
88struct State<S> {
91 sink: S,
92 head: OwnedPartHead,
93 text: WipeVec,
94 sniff: WipeVec,
95 sniff_len: usize,
96 value_cap: usize,
97 skip_empty: bool,
98 part: Part,
99}
100
101#[derive(Clone, Copy, PartialEq, Eq)]
103enum Next {
104 Continue,
105 SkipPart,
106}
107
108fn refused(v: Verdict, at: Location) -> Result<bool, FormError> {
109 match v {
110 Verdict::Refuse(refusal) => Err(FormError::Refused { refusal, at }),
111 Verdict::Skip => Ok(true),
112 _ => Ok(false),
113 }
114}
115
116impl<S: Sink> State<S> {
117 fn start_file<I: Inspector>(
118 &mut self,
119 head: &PartHead<'_>,
120 inspector: &mut I,
121 at: Location,
122 ) -> Result<Next, FormError> {
123 if refused(inspector.part_start(head), at)? {
124 self.part = Part::File {
125 open: false,
126 deferred: false,
127 sniffing: false,
128 skip: true,
129 };
130 return Ok(Next::SkipPart);
131 }
132 crate::wipe::wipe(&mut self.sniff);
136 self.sniff.clear();
137 self.part = Part::File {
138 open: false,
139 deferred: false,
140 sniffing: self.sniff_len > 0,
141 skip: false,
142 };
143 Ok(Next::Continue)
144 }
145
146 fn on_start<I: Inspector>(
147 &mut self,
148 head: &PartHead<'_>,
149 declared: TextRule,
150 inspector: &mut I,
151 at: Location,
152 ) -> Result<Next, FormError> {
153 self.head.copy_from(head);
154 match head.kind() {
155 PartKind::File => {
156 let empty = head.filename().is_some_and(|f| f.is_empty());
157 if empty && self.skip_empty {
158 self.part = Part::File {
159 open: false,
160 deferred: true,
161 sniffing: false,
162 skip: false,
163 };
164 return Ok(Next::Continue);
165 }
166 self.start_file(head, inspector, at)
167 }
168 _ => {
169 crate::wipe::wipe(&mut self.text);
170 self.text.clear();
171 let rule = head.charset().rule(declared);
172 if refused(inspector.part_start(head), at)? {
173 self.part = Part::Field { skip: true, rule };
174 return Ok(Next::SkipPart);
175 }
176 self.part = Part::Field { skip: false, rule };
177 Ok(Next::Continue)
178 }
179 }
180 }
181
182 fn ensure_open(&mut self) -> Result<(), FormError> {
184 if let Part::File { open: false, .. } = self.part {
185 self.sink.open(&self.head.view())?;
186 if let Part::File { open, .. } = &mut self.part {
187 *open = true;
188 }
189 }
190 Ok(())
191 }
192
193 fn skip_file(&mut self) {
195 if let Part::File { open: true, .. } = self.part {
196 self.sink.abort();
197 }
198 self.part = Part::File {
199 open: false,
200 deferred: false,
201 sniffing: false,
202 skip: true,
203 };
204 }
205
206 fn file_bytes<I: Inspector>(
208 &mut self,
209 index: u32,
210 bytes: &[u8],
211 inspector: &mut I,
212 at: Location,
213 ) -> Result<Next, FormError> {
214 if bytes.is_empty() {
215 return Ok(Next::Continue);
216 }
217 if refused(inspector.data(index, bytes), at)? {
218 self.skip_file();
219 return Ok(Next::SkipPart);
220 }
221 self.ensure_open()?;
222 self.sink.write(bytes).map(|()| Next::Continue)
223 }
224
225 fn flush_sniff<I: Inspector>(
227 &mut self,
228 index: u32,
229 inspector: &mut I,
230 at: Location,
231 ) -> Result<Next, FormError> {
232 if let Part::File { sniffing, .. } = &mut self.part {
233 *sniffing = false;
234 }
235 let window = core::mem::take(&mut self.sniff);
236 let verdict = inspector.sniff(&self.head.view(), &window);
237 let result = match refused(verdict, at) {
238 Err(e) => Err(e),
239 Ok(true) => {
240 self.skip_file();
241 Ok(Next::SkipPart)
242 }
243 Ok(false) => self.file_bytes(index, &window, inspector, at),
244 };
245 self.sniff = window;
246 crate::wipe::wipe(&mut self.sniff);
247 self.sniff.clear();
248 result
249 }
250
251 fn on_data<I: Inspector>(
252 &mut self,
253 bytes: &[u8],
254 inspector: &mut I,
255 at: Location,
256 ) -> Result<Next, FormError> {
257 let index = self.head.view().index();
258 match self.part {
259 Part::Field { skip: false, rule } => {
260 if refused(inspector.data(index, bytes), at)? {
261 self.part = Part::Field { skip: true, rule };
262 return Ok(Next::SkipPart);
263 }
264 crate::wipe::append_wiping(&mut self.text, bytes, 256, self.value_cap);
265 Ok(Next::Continue)
266 }
267 Part::File { deferred: true, .. } => {
268 let head = self.head.clone();
269 if self.start_file(&head.view(), inspector, at)? == Next::SkipPart {
270 return Ok(Next::SkipPart);
271 }
272 self.on_data(bytes, inspector, at)
273 }
274 Part::File {
275 skip: false,
276 sniffing: true,
277 ..
278 } => {
279 let room = self.sniff_len.saturating_sub(self.sniff.len());
280 let (head, rest) = bytes.split_at(room.min(bytes.len()));
281 self.sniff.extend_from_slice(head);
282 if self.sniff.len() < self.sniff_len {
283 return Ok(Next::Continue);
284 }
285 if self.flush_sniff(index, inspector, at)? == Next::SkipPart {
286 return Ok(Next::SkipPart);
287 }
288 self.file_bytes(index, rest, inspector, at)
289 }
290 Part::File { skip: false, .. } => self.file_bytes(index, bytes, inspector, at),
291 _ => Ok(Next::Continue),
292 }
293 }
294}
295
296enum Done<F> {
298 Field,
299 File(F),
300 NeedInput,
301 End,
302}
303
304pub struct Driver<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> {
326 parser: MultipartParser<B>,
327 state: State<S>,
328 ended: bool,
329 failed: bool,
330}
331
332impl<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> fmt::Debug for Driver<B, S> {
333 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334 f.debug_struct("Driver")
335 .field("parser", &self.parser)
336 .field("ended", &self.ended)
337 .finish_non_exhaustive()
338 }
339}
340
341impl<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> Driver<B, S> {
342 #[must_use]
355 pub fn new(parser: MultipartParser<B>, sink: S) -> Self {
356 let limits = *parser.limits();
357 let policy = *parser.policy();
358 let sniff_len = limits.sniff() as usize;
359 Driver {
360 state: State {
361 sink,
362 head: OwnedPartHead::with_capacity(limits.multipart_buffer_len(&policy)),
363 text: WipeVec::default(),
364 sniff: WipeVec(Vec::with_capacity(sniff_len)),
365 sniff_len,
366 value_cap: limits.value() as usize,
367 skip_empty: policy.empty_files == EmptyFilePolicy::Skip,
368 part: Part::Idle,
369 },
370 parser,
371 ended: false,
372 failed: false,
373 }
374 }
375
376 #[must_use]
391 pub const fn parser(&self) -> &MultipartParser<B> {
392 &self.parser
393 }
394
395 pub fn into_parts(self) -> (MultipartParser<B>, S) {
409 (self.parser, self.state.sink)
410 }
411
412 pub fn push<'d, I: Inspector>(
438 &'d mut self,
439 input: &[u8],
440 eof: bool,
441 inspector: &mut I,
442 ) -> Result<(usize, Progress<'d, S::Output>), FormError> {
443 if self.failed {
444 return Err(FormError::Poisoned);
445 }
446 match self.run(input, eof, inspector) {
447 Ok((consumed, done)) => Ok((
448 consumed,
449 match done {
450 Done::Field => Progress::Field {
451 name: self.state.head_name(),
452 value: &self.state.text,
453 },
454 Done::File(f) => Progress::File(f),
455 Done::NeedInput => Progress::NeedInput,
456 Done::End => Progress::End,
457 },
458 )),
459 Err(e) => {
460 self.failed = true;
461 self.state.sink.abort();
462 inspector.failed(&e);
463 Err(e)
464 }
465 }
466 }
467
468 fn at(&self) -> Location {
469 Location::in_part(
470 self.parser.parts_seen().checked_sub(1),
471 self.parser.bytes_seen(),
472 )
473 }
474
475 fn run<I: Inspector>(
476 &mut self,
477 input: &[u8],
478 eof: bool,
479 inspector: &mut I,
480 ) -> Result<(usize, Done<S::Output>), FormError> {
481 let mut pos = 0usize;
482 loop {
483 let rest = input.get(pos..).unwrap_or(&[]);
484 let seen = self.parser.bytes_seen();
485 let parts = self.parser.parts_seen();
486 let declared = crate::multipart::parser::declared_rule(self.parser.declared_charset());
489 let step = self.parser.parse(rest, eof)?;
490 pos = pos.saturating_add(step.consumed);
491 let index = match &step.event {
492 MultipartEvent::PartStart(head) => Some(head.index()),
493 _ => parts.checked_sub(1),
494 };
495 let at = Location::in_part(index, seen.saturating_add(step.consumed as u64));
496 let next = match step.event {
497 MultipartEvent::PartStart(head) => {
498 self.state.on_start(&head, declared, inspector, at)?
499 }
500 MultipartEvent::Data(bytes) => self.state.on_data(bytes, inspector, at)?,
501 MultipartEvent::PartEnd(summary) => {
502 if let Some(done) = self.on_end(summary, inspector)? {
503 return Ok((pos, done));
504 }
505 Next::Continue
506 }
507 MultipartEvent::End => {
508 if !self.ended {
509 self.ended = true;
510 if let Verdict::Refuse(refusal) = inspector.end() {
511 return Err(FormError::Refused { refusal, at });
512 }
513 }
514 return Ok((pos, Done::End));
515 }
516 _ => return Ok((pos, Done::NeedInput)),
517 };
518 if next == Next::SkipPart {
519 self.parser.skip_part();
520 }
521 }
522 }
523
524 fn on_end<I: Inspector>(
525 &mut self,
526 summary: PartSummary,
527 inspector: &mut I,
528 ) -> Result<Option<Done<S::Output>>, FormError> {
529 let at = self.at();
530 let part = core::mem::replace(&mut self.state.part, Part::Idle);
531 let skipped = summary.skipped
532 || matches!(
533 part,
534 Part::Field { skip: true, .. } | Part::File { skip: true, .. }
535 );
536 let summary = PartSummary { skipped, ..summary };
537 match part {
538 Part::File { deferred: true, .. } => Ok(None),
539 Part::File {
540 skip: false,
541 sniffing,
542 ..
543 } => {
544 self.state.part = part;
547 let flushed = if sniffing {
548 self.state.flush_sniff(summary.index, inspector, at)
549 } else {
550 Ok(Next::Continue)
551 };
552 let opened = match flushed {
553 Ok(Next::Continue) => self.state.ensure_open().map(|()| true),
554 Ok(Next::SkipPart) => Ok(false),
555 Err(e) => Err(e),
556 };
557 self.state.part = Part::Idle;
558 if !opened? {
559 let summary = PartSummary {
560 skipped: true,
561 ..summary
562 };
563 refused(inspector.part_end(&summary), at)?;
564 return Ok(None);
565 }
566 refused(inspector.part_end(&summary), at)?;
570 let output = self.state.sink.close()?;
571 Ok(Some(Done::File(output)))
572 }
573 Part::Field { skip: false, rule } => {
574 let text_at = Location::in_part(Some(summary.index), at.offset);
578 rule.check(&self.state.text)
579 .map_err(|reason| FormError::encoding(reason, text_at))?;
580 let name = self.state.head.view().name();
581 let skip = refused(inspector.field(name, &self.state.text), at)?;
584 let summary = PartSummary {
585 skipped: skip,
586 ..summary
587 };
588 refused(inspector.part_end(&summary), at)?;
589 if skip {
590 crate::wipe::wipe(&mut self.state.text);
591 return Ok(None);
592 }
593 Ok(Some(Done::Field))
594 }
595 _ => {
596 refused(inspector.part_end(&summary), at)?;
597 Ok(None)
598 }
599 }
600 }
601}
602
603impl<S> State<S> {
604 fn head_name(&self) -> &str {
605 self.head.view().name()
606 }
607}
608
609impl<B: AsMut<[u8]> + AsRef<[u8]>, S: Sink> Driver<B, S> {
610 #[cfg(feature = "fs")]
612 pub(crate) const fn has_failed(&self) -> bool {
613 self.failed
614 }
615}