Separate HttpPostedFile

This commit is contained in:
Bond-009 2019-02-16 11:37:25 +01:00
parent 25c2267a89
commit fb6a901374
4 changed files with 248 additions and 248 deletions

View File

@ -6,9 +6,13 @@ namespace Jellyfin.Server.SocketSharp
public class HttpFile : IHttpFile public class HttpFile : IHttpFile
{ {
public string Name { get; set; } public string Name { get; set; }
public string FileName { get; set; } public string FileName { get; set; }
public long ContentLength { get; set; } public long ContentLength { get; set; }
public string ContentType { get; set; } public string ContentType { get; set; }
public Stream InputStream { get; set; } public Stream InputStream { get; set; }
} }
} }

View File

@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
public sealed class HttpPostedFile : IDisposable
{
private string _name;
private string _contentType;
private Stream _stream;
private bool _disposed = false;
internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length)
{
_name = name;
_contentType = content_type;
_stream = new ReadSubStream(base_stream, offset, length);
}
public string ContentType => _contentType;
public int ContentLength => (int)_stream.Length;
public string FileName => _name;
public Stream InputStream => _stream;
/// <summary>
/// Releases the unmanaged resources and disposes of the managed resources used.
/// </summary>
public void Dispose()
{
if (_disposed)
{
return;
}
_stream.Dispose();
_stream = null;
_name = null;
_contentType = null;
_disposed = true;
}
private class ReadSubStream : Stream
{
private Stream _stream;
private long _offset;
private long _end;
private long _position;
public ReadSubStream(Stream s, long offset, long length)
{
_stream = s;
_offset = offset;
_end = offset + length;
_position = offset;
}
public override void Flush()
{
}
public override int Read(byte[] buffer, int dest_offset, int count)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (dest_offset < 0)
{
throw new ArgumentOutOfRangeException(nameof(dest_offset), "< 0");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "< 0");
}
int len = buffer.Length;
if (dest_offset > len)
{
throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset));
}
// reordered to avoid possible integer overflow
if (dest_offset > len - count)
{
throw new ArgumentException("Reading would overrun buffer", nameof(count));
}
if (count > _end - _position)
{
count = (int)(_end - _position);
}
if (count <= 0)
{
return 0;
}
_stream.Position = _position;
int result = _stream.Read(buffer, dest_offset, count);
if (result > 0)
{
_position += result;
}
else
{
_position = _end;
}
return result;
}
public override int ReadByte()
{
if (_position >= _end)
{
return -1;
}
_stream.Position = _position;
int result = _stream.ReadByte();
if (result < 0)
{
_position = _end;
}
else
{
_position++;
}
return result;
}
public override long Seek(long d, SeekOrigin origin)
{
long real;
switch (origin)
{
case SeekOrigin.Begin:
real = _offset + d;
break;
case SeekOrigin.End:
real = _end + d;
break;
case SeekOrigin.Current:
real = _position + d;
break;
default:
throw new ArgumentException("Unknown SeekOrigin value", nameof(origin));
}
long virt = real - _offset;
if (virt < 0 || virt > Length)
{
throw new ArgumentException("Invalid position", nameof(d));
}
_position = _stream.Seek(real, SeekOrigin.Begin);
return _position;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => _end - _offset;
public override long Position
{
get => _position - _offset;
set
{
if (value > Length)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_position = Seek(value, SeekOrigin.Begin);
}
}
}
}

View File

@ -225,7 +225,7 @@ namespace Jellyfin.Server.SocketSharp
if (starts_with) if (starts_with)
{ {
return StrUtils.StartsWith(ContentType, ct, true); return ContentType.StartsWith(ct, StringComparison.OrdinalIgnoreCase);
} }
return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase); return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase);
@ -324,215 +324,6 @@ namespace Jellyfin.Server.SocketSharp
return result.ToString(); return result.ToString();
} }
} }
public sealed class HttpPostedFile
{
private string name;
private string content_type;
private Stream stream;
private class ReadSubStream : Stream
{
private Stream s;
private long offset;
private long end;
private long position;
public ReadSubStream(Stream s, long offset, long length)
{
this.s = s;
this.offset = offset;
this.end = offset + length;
position = offset;
}
public override void Flush()
{
}
public override int Read(byte[] buffer, int dest_offset, int count)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (dest_offset < 0)
{
throw new ArgumentOutOfRangeException(nameof(dest_offset), "< 0");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "< 0");
}
int len = buffer.Length;
if (dest_offset > len)
{
throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset));
}
// reordered to avoid possible integer overflow
if (dest_offset > len - count)
{
throw new ArgumentException("Reading would overrun buffer", nameof(count));
}
if (count > end - position)
{
count = (int)(end - position);
}
if (count <= 0)
{
return 0;
}
s.Position = position;
int result = s.Read(buffer, dest_offset, count);
if (result > 0)
{
position += result;
}
else
{
position = end;
}
return result;
}
public override int ReadByte()
{
if (position >= end)
{
return -1;
}
s.Position = position;
int result = s.ReadByte();
if (result < 0)
{
position = end;
}
else
{
position++;
}
return result;
}
public override long Seek(long d, SeekOrigin origin)
{
long real;
switch (origin)
{
case SeekOrigin.Begin:
real = offset + d;
break;
case SeekOrigin.End:
real = end + d;
break;
case SeekOrigin.Current:
real = position + d;
break;
default:
throw new ArgumentException("Unknown SeekOrigin value", nameof(origin));
}
long virt = real - offset;
if (virt < 0 || virt > Length)
{
throw new ArgumentException("Invalid position", nameof(d));
}
position = s.Seek(real, SeekOrigin.Begin);
return position;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => end - offset;
public override long Position
{
get => position - offset;
set
{
if (value > Length)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
position = Seek(value, SeekOrigin.Begin);
}
}
}
internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length)
{
this.name = name;
this.content_type = content_type;
this.stream = new ReadSubStream(base_stream, offset, length);
}
public string ContentType => content_type;
public int ContentLength => (int)stream.Length;
public string FileName => name;
public Stream InputStream => stream;
}
internal static class StrUtils
{
public static bool StartsWith(string str1, string str2, bool ignore_case)
{
if (string.IsNullOrEmpty(str1))
{
return false;
}
var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
return str1.IndexOf(str2, comparison) == 0;
}
public static bool EndsWith(string str1, string str2, bool ignore_case)
{
int l2 = str2.Length;
if (l2 == 0)
{
return true;
}
int l1 = str1.Length;
if (l2 > l1)
{
return false;
}
var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
return str1.IndexOf(str2, comparison) == str1.Length - str2.Length - 1;
}
}
private class HttpMultipart private class HttpMultipart
{ {
@ -606,12 +397,12 @@ namespace Jellyfin.Server.SocketSharp
string header; string header;
while ((header = ReadHeaders()) != null) while ((header = ReadHeaders()) != null)
{ {
if (StrUtils.StartsWith(header, "Content-Disposition:", true)) if (header.StartsWith("Content-Disposition:", StringComparison.OrdinalIgnoreCase))
{ {
elem.Name = GetContentDispositionAttribute(header, "name"); elem.Name = GetContentDispositionAttribute(header, "name");
elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename"));
} }
else if (StrUtils.StartsWith(header, "Content-Type:", true)) else if (header.StartsWith("Content-Type:", StringComparison.OrdinalIgnoreCase))
{ {
elem.ContentType = header.Substring("Content-Type:".Length).Trim(); elem.ContentType = header.Substring("Content-Type:".Length).Trim();
elem.Encoding = GetEncoding(elem.ContentType); elem.Encoding = GetEncoding(elem.ContentType);
@ -730,13 +521,14 @@ namespace Jellyfin.Server.SocketSharp
return false; return false;
} }
if (!StrUtils.EndsWith(line, boundary, false)) if (!line.EndsWith(boundary, StringComparison.Ordinal))
{ {
return true; return true;
} }
} }
catch catch
{ {
} }
return false; return false;

View File

@ -55,6 +55,41 @@ namespace Jellyfin.Server.SocketSharp
public QueryParamCollection Headers => _response.Headers; public QueryParamCollection Headers => _response.Headers;
private static string AsHeaderValue(Cookie cookie)
{
DateTime defaultExpires = DateTime.MinValue;
var path = cookie.Expires == defaultExpires
? "/"
: cookie.Path ?? "/";
var sb = new StringBuilder();
sb.Append($"{cookie.Name}={cookie.Value};path={path}");
if (cookie.Expires != defaultExpires)
{
sb.Append($";expires={cookie.Expires:R}");
}
if (!string.IsNullOrEmpty(cookie.Domain))
{
sb.Append($";domain={cookie.Domain}");
}
if (cookie.Secure)
{
sb.Append(";Secure");
}
if (cookie.HttpOnly)
{
sb.Append(";HttpOnly");
}
return sb.ToString();
}
public void AddHeader(string name, string value) public void AddHeader(string name, string value)
{ {
if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase)) if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase))
@ -126,41 +161,6 @@ namespace Jellyfin.Server.SocketSharp
_response.Headers.Add("Set-Cookie", cookieStr); _response.Headers.Add("Set-Cookie", cookieStr);
} }
public static string AsHeaderValue(Cookie cookie)
{
var defaultExpires = DateTime.MinValue;
var path = cookie.Expires == defaultExpires
? "/"
: cookie.Path ?? "/";
var sb = new StringBuilder();
sb.Append($"{cookie.Name}={cookie.Value};path={path}");
if (cookie.Expires != defaultExpires)
{
sb.Append($";expires={cookie.Expires:R}");
}
if (!string.IsNullOrEmpty(cookie.Domain))
{
sb.Append($";domain={cookie.Domain}");
}
if (cookie.Secure)
{
sb.Append(";Secure");
}
if (cookie.HttpOnly)
{
sb.Append(";HttpOnly");
}
return sb.ToString();
}
public bool SendChunked public bool SendChunked
{ {
get => _response.SendChunked; get => _response.SendChunked;