1use crate::MultipartError;
2use crate::payload::{PayloadBuffer, PayloadRef};
3use crate::safety::Safety;
4use futures::Stream;
5use ntex::http::error::PayloadError;
6use ntex::http::{HeaderMap, header};
7use ntex::util::Bytes;
8use ntex_files::header::ContentDisposition;
9use std::cell::RefCell;
10use std::pin::Pin;
11use std::rc::Rc;
12use std::task::{Context, Poll};
13use std::{cmp, fmt};
14
15pub struct Field {
17 content_type: Option<mime::Mime>,
19
20 content_disposition: Option<ContentDisposition>,
22
23 pub(crate) form_field_name: String,
25
26 headers: HeaderMap,
28
29 inner: Rc<RefCell<InnerField>>,
30 safety: Safety,
31}
32
33impl Field {
34 pub(crate) fn new(
35 safety: Safety,
36 headers: HeaderMap,
37 content_type: Option<mime::Mime>,
38 content_disposition: Option<ContentDisposition>,
39 form_field_name: Option<String>,
40 inner: Rc<RefCell<InnerField>>,
41 ) -> Self {
42 Field {
43 content_type,
44 content_disposition,
45 form_field_name: form_field_name.unwrap_or_default(),
46 headers,
47 inner,
48 safety,
49 }
50 }
51
52 pub fn headers(&self) -> &HeaderMap {
54 &self.headers
55 }
56
57 pub fn content_type(&self) -> Option<&mime::Mime> {
59 self.content_type.as_ref()
60 }
61
62 pub fn content_disposition(&self) -> Option<&ContentDisposition> {
64 self.content_disposition.as_ref()
65 }
66
67 pub fn name(&self) -> Option<&str> {
69 self.content_disposition()?.get_name()
70 }
71}
72
73impl Stream for Field {
74 type Item = Result<Bytes, MultipartError>;
75
76 fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
77 if self.safety.current() {
78 let mut inner = self.inner.borrow_mut();
79 if let Some(mut payload) = inner.payload.as_ref().unwrap().get_mut(&self.safety) {
80 payload.poll_stream(cx)?;
81 }
82 inner.poll(&self.safety)
83 } else if !self.safety.is_clean() {
84 Poll::Ready(Some(Err(MultipartError::NotConsumed)))
85 } else {
86 Poll::Pending
87 }
88 }
89}
90
91impl fmt::Debug for Field {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 if let Some(ct) = &self.content_type {
94 writeln!(f, "\nField: {}", ct)?;
95 } else {
96 writeln!(f, "\nField:")?;
97 }
98 writeln!(f, " boundary: {}", self.inner.borrow().boundary)?;
99 writeln!(f, " headers:")?;
100 for (key, val) in self.headers.iter() {
101 writeln!(f, " {:?}: {:?}", key, val)?;
102 }
103 Ok(())
104 }
105}
106
107pub(crate) struct InnerField {
108 payload: Option<PayloadRef>,
109 boundary: String,
110 eof: bool,
111 length: Option<u64>,
112}
113
114impl InnerField {
115 pub(crate) fn new(
116 payload: PayloadRef,
117 boundary: String,
118 headers: &HeaderMap,
119 ) -> Result<InnerField, PayloadError> {
120 let len = if let Some(len) = headers.get(&header::CONTENT_LENGTH) {
121 if let Ok(s) = len.to_str() {
122 if let Ok(len) = s.parse::<u64>() {
123 Some(len)
124 } else {
125 return Err(PayloadError::Incomplete(None));
126 }
127 } else {
128 return Err(PayloadError::Incomplete(None));
129 }
130 } else {
131 None
132 };
133
134 Ok(InnerField { boundary, payload: Some(payload), eof: false, length: len })
135 }
136
137 pub(crate) fn read_len(
140 payload: &mut PayloadBuffer,
141 size: &mut u64,
142 ) -> Poll<Option<Result<Bytes, MultipartError>>> {
143 if *size == 0 {
144 Poll::Ready(None)
145 } else {
146 match payload.read_max(*size)? {
147 Some(mut chunk) => {
148 let len = cmp::min(chunk.len() as u64, *size);
149 *size -= len;
150 let ch = chunk.split_to(len as usize);
151 if !chunk.is_empty() {
152 payload.unprocessed(chunk);
153 }
154 Poll::Ready(Some(Ok(ch)))
155 }
156 None => {
157 if payload.eof && (*size != 0) {
158 Poll::Ready(Some(Err(MultipartError::Incomplete)))
159 } else {
160 Poll::Pending
161 }
162 }
163 }
164 }
165 }
166
167 pub(crate) fn read_stream(
170 payload: &mut PayloadBuffer,
171 boundary: &str,
172 ) -> Poll<Option<Result<Bytes, MultipartError>>> {
173 let mut pos = 0;
174
175 let len = payload.buf.len();
176 if len == 0 {
177 return if payload.eof {
178 Poll::Ready(Some(Err(MultipartError::Incomplete)))
179 } else {
180 Poll::Pending
181 };
182 }
183
184 if len > 4 && payload.buf[0] == b'\r' {
186 let b_len = if &payload.buf[..2] == b"\r\n" && &payload.buf[2..4] == b"--" {
187 Some(4)
188 } else if &payload.buf[1..3] == b"--" {
189 Some(3)
190 } else {
191 None
192 };
193
194 if let Some(b_len) = b_len {
195 let b_size = boundary.len() + b_len;
196 if len < b_size {
197 return Poll::Pending;
198 } else if &payload.buf[b_len..b_size] == boundary.as_bytes() {
199 return Poll::Ready(None);
201 }
202 }
203 }
204
205 loop {
206 return if let Some(idx) = twoway::find_bytes(&payload.buf[pos..], b"\r") {
207 let cur = pos + idx;
208
209 if cur + 4 > len {
211 if cur > 0 {
212 Poll::Ready(Some(Ok(payload.buf.split_to(cur))))
213 } else {
214 Poll::Pending
215 }
216 } else {
217 if (&payload.buf[cur..cur + 2] == b"\r\n"
219 && &payload.buf[cur + 2..cur + 4] == b"--")
220 || (&payload.buf[cur..=cur] == b"\r"
221 && &payload.buf[cur + 1..cur + 3] == b"--")
222 {
223 if cur != 0 {
224 Poll::Ready(Some(Ok(payload.buf.split_to(cur))))
226 } else {
227 pos = cur + 1;
228 continue;
229 }
230 } else {
231 pos = cur + 1;
233 continue;
234 }
235 }
236 } else {
237 Poll::Ready(Some(Ok(payload.buf.take())))
238 };
239 }
240 }
241
242 pub(crate) fn poll(&mut self, s: &Safety) -> Poll<Option<Result<Bytes, MultipartError>>> {
243 if self.payload.is_none() {
244 return Poll::Ready(None);
245 }
246
247 let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s) {
248 if !self.eof {
249 let res = if let Some(ref mut len) = self.length {
250 InnerField::read_len(&mut payload, len)
251 } else {
252 InnerField::read_stream(&mut payload, &self.boundary)
253 };
254
255 match res {
256 Poll::Pending => return Poll::Pending,
257 Poll::Ready(Some(Ok(bytes))) => return Poll::Ready(Some(Ok(bytes))),
258 Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))),
259 Poll::Ready(None) => self.eof = true,
260 }
261 }
262
263 match payload.readline() {
264 Ok(None) => Poll::Pending,
265 Ok(Some(line)) => {
266 if line.as_ref() != b"\r\n" {
267 log::warn!(
268 "multipart field did not read all the data or it is malformed"
269 );
270 }
271 Poll::Ready(None)
272 }
273 Err(e) => Poll::Ready(Some(Err(e))),
274 }
275 } else {
276 Poll::Pending
277 };
278
279 if let Poll::Ready(None) = result {
280 self.payload.take();
281 }
282 result
283 }
284}