Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
MultipartContent.cs
Go to the documentation of this file.
5using System.IO;
7using System.Text;
10
11namespace System.Net.Http;
12
14{
15 private sealed class ContentReadStream : Stream
16 {
17 private readonly Stream[] _streams;
18
19 private readonly long _length;
20
21 private int _next;
22
24
25 private long _position;
26
27 public override bool CanRead => true;
28
29 public override bool CanSeek => true;
30
31 public override bool CanWrite => false;
32
33 public override long Position
34 {
35 get
36 {
37 return _position;
38 }
39 set
40 {
41 if (value < 0)
42 {
43 throw new ArgumentOutOfRangeException("value");
44 }
45 long num = 0L;
46 for (int i = 0; i < _streams.Length; i++)
47 {
49 long length = stream.Length;
50 if (value < num + length)
51 {
53 i = (_next = i + 1);
54 stream.Position = value - num;
55 for (; i < _streams.Length; i++)
56 {
57 _streams[i].Position = 0L;
58 }
60 return;
61 }
62 num += length;
63 }
64 _current = null;
67 }
68 }
69
70 public override long Length => _length;
71
73 {
75 foreach (Stream stream in streams)
76 {
77 _length += stream.Length;
78 }
79 }
80
81 protected override void Dispose(bool disposing)
82 {
83 if (disposing)
84 {
86 foreach (Stream stream in streams)
87 {
89 }
90 }
91 }
92
93 public override async ValueTask DisposeAsync()
94 {
96 foreach (Stream stream in streams)
97 {
98 await stream.DisposeAsync().ConfigureAwait(continueOnCapturedContext: false);
99 }
100 }
101
102 public override int Read(byte[] buffer, int offset, int count)
103 {
105 if (count == 0)
106 {
107 return 0;
108 }
109 while (true)
110 {
111 if (_current != null)
112 {
113 int num = _current.Read(buffer, offset, count);
114 if (num != 0)
115 {
116 _position += num;
117 return num;
118 }
119 _current = null;
120 }
121 if (_next >= _streams.Length)
122 {
123 break;
124 }
126 }
127 return 0;
128 }
129
130 public override int Read(Span<byte> buffer)
131 {
132 if (buffer.Length == 0)
133 {
134 return 0;
135 }
136 while (true)
137 {
138 if (_current != null)
139 {
140 int num = _current.Read(buffer);
141 if (num != 0)
142 {
143 _position += num;
144 return num;
145 }
146 _current = null;
147 }
148 if (_next >= _streams.Length)
149 {
150 break;
151 }
153 }
154 return 0;
155 }
156
162
167
168 public override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState)
169 {
171 }
172
173 public override int EndRead(IAsyncResult asyncResult)
174 {
176 }
177
179 {
180 if (buffer.Length == 0)
181 {
182 return 0;
183 }
184 while (true)
185 {
186 if (_current != null)
187 {
189 if (num != 0)
190 {
191 _position += num;
192 return num;
193 }
194 _current = null;
195 }
196 if (_next >= _streams.Length)
197 {
198 break;
199 }
201 }
202 return 0;
203 }
204
205 public override long Seek(long offset, SeekOrigin origin)
206 {
207 switch (origin)
208 {
209 case SeekOrigin.Begin:
211 break;
212 case SeekOrigin.Current:
213 Position += offset;
214 break;
215 case SeekOrigin.End:
217 break;
218 default:
219 throw new ArgumentOutOfRangeException("origin");
220 }
221 return Position;
222 }
223
224 public override void Flush()
225 {
226 }
227
228 public override void SetLength(long value)
229 {
230 throw new NotSupportedException();
231 }
232
233 public override void Write(byte[] buffer, int offset, int count)
234 {
235 throw new NotSupportedException();
236 }
237
238 public override void Write(ReadOnlySpan<byte> buffer)
239 {
240 throw new NotSupportedException();
241 }
242
244 {
245 throw new NotSupportedException();
246 }
247
252 }
253
255
256 private readonly string _boundary;
257
259
260 internal override bool AllowDuplex => false;
261
263 : this("mixed", GetDefaultBoundary())
264 {
265 }
266
269 {
270 }
271
272 public MultipartContent(string subtype, string boundary)
273 {
274 if (string.IsNullOrWhiteSpace(subtype))
275 {
277 }
280 string text = boundary;
281 if (!text.StartsWith('"'))
282 {
283 text = "\"" + text + "\"";
284 }
286 {
287 Parameters =
288 {
289 new NameValueHeaderValue("boundary", text)
290 }
291 };
292 base.Headers.ContentType = contentType;
294 }
295
296 private static void ValidateBoundary(string boundary)
297 {
298 if (string.IsNullOrWhiteSpace(boundary))
299 {
301 }
302 if (boundary.Length > 70)
303 {
305 }
306 if (boundary.EndsWith(' '))
307 {
309 }
310 foreach (char c in boundary)
311 {
312 if (('0' > c || c > '9') && ('a' > c || c > 'z') && ('A' > c || c > 'Z') && !"'()+_,-./:=? ".Contains(c))
313 {
315 }
316 }
317 }
318
319 private static string GetDefaultBoundary()
320 {
321 return Guid.NewGuid().ToString();
322 }
323
324 public virtual void Add(HttpContent content)
325 {
326 if (content == null)
327 {
328 throw new ArgumentNullException("content");
329 }
330 _nestedContent.Add(content);
331 }
332
333 protected override void Dispose(bool disposing)
334 {
335 if (disposing)
336 {
337 foreach (HttpContent item in _nestedContent)
338 {
339 item.Dispose();
340 }
342 }
343 base.Dispose(disposing);
344 }
345
350
355
357 {
358 try
359 {
360 WriteToStream(stream, "--" + _boundary + "\r\n");
361 for (int i = 0; i < _nestedContent.Count; i++)
362 {
366 }
367 WriteToStream(stream, "\r\n--" + _boundary + "--\r\n");
368 }
369 catch (Exception message)
370 {
371 if (System.Net.NetEventSource.Log.IsEnabled())
372 {
373 System.Net.NetEventSource.Error(this, message, "SerializeToStream");
374 }
375 throw;
376 }
377 }
378
380 {
381 return SerializeToStreamAsyncCore(stream, context, default(CancellationToken));
382 }
383
385 {
386 if (!(GetType() == typeof(MultipartContent)))
387 {
388 return base.SerializeToStreamAsync(stream, context, cancellationToken);
389 }
391 }
392
394 {
395 _ = 3;
396 try
397 {
401 {
403 output.SetLength(0L);
405 output.Position = 0L;
406 await output.CopyToAsync(stream, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
408 }
409 await EncodeStringToStreamAsync(stream, "\r\n--" + _boundary + "--\r\n", cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
410 }
411 catch (Exception message)
412 {
413 if (System.Net.NetEventSource.Log.IsEnabled())
414 {
415 System.Net.NetEventSource.Error(this, message, "SerializeToStreamAsyncCore");
416 }
417 throw;
418 }
419 }
420
422 {
423 return CreateContentReadStreamAsyncCore(async: false, cancellationToken).GetAwaiter().GetResult();
424 }
425
427 {
429 }
430
432 {
433 if (!(GetType() == typeof(MultipartContent)))
434 {
435 return base.CreateContentReadStreamAsync(cancellationToken);
436 }
438 }
439
441 {
442 _ = 1;
443 try
444 {
445 Stream[] streams = new Stream[2 + _nestedContent.Count * 2];
446 int streamIndex = 0;
449 {
450 cancellationToken.ThrowIfCancellationRequested();
454 if (async)
455 {
456 Stream stream = httpContent.TryReadAsStream();
458 if (stream2 == null)
459 {
460 stream2 = await httpContent.ReadAsStreamAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
461 }
463 }
464 else
465 {
466 stream3 = httpContent.ReadAsStream(cancellationToken);
467 }
468 if (stream3 == null)
469 {
470 stream3 = new MemoryStream();
471 }
472 if (!stream3.CanSeek)
473 {
474 return (!async) ? base.CreateContentReadStream(cancellationToken) : (await base.CreateContentReadStreamAsync().ConfigureAwait(continueOnCapturedContext: false));
475 }
477 }
478 streams[streamIndex] = EncodeStringToNewStream("\r\n--" + _boundary + "--\r\n");
479 return new ContentReadStream(streams);
480 }
481 catch (Exception message)
482 {
483 if (System.Net.NetEventSource.Log.IsEnabled())
484 {
485 System.Net.NetEventSource.Error(this, message, "CreateContentReadStreamAsyncCore");
486 }
487 throw;
488 }
489 }
490
492 {
493 if (writeDivider)
494 {
495 WriteToStream(stream, "\r\n--");
497 WriteToStream(stream, "\r\n");
498 }
499 foreach (KeyValuePair<string, HeaderStringValues> item in content.Headers.NonValidated)
500 {
501 Encoding encoding = HeaderEncodingSelector?.Invoke(item.Key, content) ?? HttpRuleParser.DefaultHttpEncoding;
503 WriteToStream(stream, ": ");
504 string content2 = string.Empty;
505 foreach (string item2 in item.Value)
506 {
508 WriteToStream(stream, item2, encoding);
509 content2 = ", ";
510 }
511 WriteToStream(stream, "\r\n");
512 }
513 WriteToStream(stream, "\r\n");
514 }
515
521
522 private static Stream EncodeStringToNewStream(string input)
523 {
524 return new MemoryStream(HttpRuleParser.DefaultHttpEncoding.GetBytes(input), writable: false);
525 }
526
528 {
531 memoryStream.Position = 0L;
532 return memoryStream;
533 }
534
535 protected internal override bool TryComputeLength(out long length)
536 {
537 long num = 2 + _boundary.Length + 2;
538 if (_nestedContent.Count > 1)
539 {
540 num += (_nestedContent.Count - 1) * (4 + _boundary.Length + 2);
541 }
542 foreach (HttpContent item in _nestedContent)
543 {
544 foreach (KeyValuePair<string, HeaderStringValues> item2 in item.Headers.NonValidated)
545 {
546 num += item2.Key.Length + 2;
548 int num2 = 0;
549 foreach (string item3 in item2.Value)
550 {
551 num += encoding.GetByteCount(item3);
552 num2++;
553 }
554 if (num2 > 1)
555 {
556 num += (num2 - 1) * 2;
557 }
558 num += 2;
559 }
560 num += 2;
561 if (!item.TryComputeLength(out var length2))
562 {
563 length = 0L;
564 return false;
565 }
566 num += length2;
567 }
568 num += 4 + _boundary.Length + 2 + 2;
569 length = num;
570 return true;
571 }
572
573 private static void WriteToStream(Stream stream, string content)
574 {
576 }
577
578 private static void WriteToStream(Stream stream, string content, Encoding encoding)
579 {
580 int maxByteCount = encoding.GetMaxByteCount(content.Length);
581 byte[] array = null;
582 Span<byte> span = ((maxByteCount > 1024) ? ((Span<byte>)(array = ArrayPool<byte>.Shared.Rent(maxByteCount))) : stackalloc byte[1024]);
584 try
585 {
586 stream.Write(bytes[..encoding.GetBytes(content, bytes)]);
587 }
588 finally
589 {
590 if (array != null)
591 {
592 ArrayPool<byte>.Shared.Return(array);
593 }
594 }
595 }
596}
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
void Add(TKey key, TValue value)
static CultureInfo InvariantCulture
static void ValidateBufferArguments(byte[] buffer, int offset, int count)
Definition Stream.cs:1044
int Read(byte[] buffer, int offset, int count)
void Dispose()
Definition Stream.cs:639
Task< int > ReadAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:762
Task CopyToAsync(Stream stream)
static Encoding DefaultHttpEncoding
override void Write(byte[] buffer, int offset, int count)
async ValueTask< int > ReadAsyncPrivate(Memory< byte > buffer, CancellationToken cancellationToken)
override Task< int > ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
override void Write(ReadOnlySpan< byte > buffer)
override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState)
override long Seek(long offset, SeekOrigin origin)
override ValueTask WriteAsync(ReadOnlyMemory< byte > buffer, CancellationToken cancellationToken=default(CancellationToken))
override ValueTask< int > ReadAsync(Memory< byte > buffer, CancellationToken cancellationToken=default(CancellationToken))
override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
override int Read(byte[] buffer, int offset, int count)
override int EndRead(IAsyncResult asyncResult)
async Task SerializeToStreamAsyncCore(Stream stream, TransportContext context, CancellationToken cancellationToken)
override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellationToken)
override bool TryComputeLength(out long length)
override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken)
Stream EncodeHeadersToNewStream(HttpContent content, bool writeDivider)
IEnumerator< HttpContent > GetEnumerator()
virtual void Add(HttpContent content)
static Stream EncodeStringToNewStream(string input)
override Task< Stream > CreateContentReadStreamAsync()
override Task SerializeToStreamAsync(Stream stream, TransportContext? context)
override Stream CreateContentReadStream(CancellationToken cancellationToken)
async ValueTask< Stream > CreateContentReadStreamAsyncCore(bool async, CancellationToken cancellationToken)
MultipartContent(string subtype, string boundary)
override void Dispose(bool disposing)
readonly List< HttpContent > _nestedContent
HeaderEncodingSelector< HttpContent >? HeaderEncodingSelector
override Task< Stream > CreateContentReadStreamAsync(CancellationToken cancellationToken)
static void WriteToStream(Stream stream, string content)
static void WriteToStream(Stream stream, string content, Encoding encoding)
static void ValidateBoundary(string boundary)
static ValueTask EncodeStringToStreamAsync(Stream stream, string input, CancellationToken cancellationToken)
void SerializeHeadersToStream(Stream stream, HttpContent content, bool writeDivider)
static readonly System.Net.NetEventSource Log
static void Error(object thisOrContextObject, FormattableString formattableString, [CallerMemberName] string memberName=null)
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_http_headers_invalid_value
Definition SR.cs:26
static string net_http_argument_empty_string
Definition SR.cs:52
static string net_http_content_field_too_long
Definition SR.cs:74
Definition SR.cs:7
virtual byte[] GetBytes(char[] chars)
Definition Encoding.cs:781
int GetMaxByteCount(int charCount)
static IAsyncResult Begin(Task task, AsyncCallback callback, object state)
Definition TaskToApm.cs:43
static void End(IAsyncResult asyncResult)
Definition TaskToApm.cs:48
new ConfiguredTaskAwaitable< TResult > ConfigureAwait(bool continueOnCapturedContext)
Definition Task.cs:226
new IEnumerator< T > GetEnumerator()
static Guid NewGuid()
Definition Guid.cs:1283