|
@@ -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;
|