aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/SocketSharp/RequestMono.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Server/SocketSharp/RequestMono.cs')
-rw-r--r--Jellyfin.Server/SocketSharp/RequestMono.cs168
1 files changed, 144 insertions, 24 deletions
diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs
index 45cb323d2..017690062 100644
--- a/Jellyfin.Server/SocketSharp/RequestMono.cs
+++ b/Jellyfin.Server/SocketSharp/RequestMono.cs
@@ -15,19 +15,27 @@ namespace Jellyfin.SocketSharp
{
int ap = header.IndexOf(attr);
if (ap == -1)
+ {
return null;
+ }
ap += attr.Length;
if (ap >= header.Length)
+ {
return null;
+ }
char ending = header[ap];
if (ending != '"')
+ {
ending = ' ';
+ }
int end = header.IndexOf(ending, ap + 1);
if (end == -1)
+ {
return ending == '"' ? null : header.Substring(ap);
+ }
return header.Substring(ap + 1, end - ap - 1);
}
@@ -36,7 +44,9 @@ namespace Jellyfin.SocketSharp
{
string boundary = GetParameter(ContentType, "; boundary=");
if (boundary == null)
+ {
return;
+ }
using (var requestStream = InputStream)
{
@@ -124,7 +134,9 @@ namespace Jellyfin.SocketSharp
{
string v = "\"" + value + "\"";
if (v.Length > 20)
+ {
v = v.Substring(0, 16) + "...\"";
+ }
string msg = string.Format("A potentially dangerous Request.{0} value was " +
"detected from the client ({1}={2}).", name, key, v);
@@ -135,21 +147,23 @@ namespace Jellyfin.SocketSharp
static void ValidateNameValueCollection(string name, QueryParamCollection coll)
{
if (coll == null)
+ {
return;
+ }
foreach (var pair in coll)
{
var key = pair.Name;
var val = pair.Value;
if (val != null && val.Length > 0 && IsInvalidString(val))
+ {
ThrowValidationException(name, key, val);
+ }
}
}
internal static bool IsInvalidString(string val)
- {
- return IsInvalidString(val, out var validationFailureIndex);
- }
+ => IsInvalidString(val, out var validationFailureIndex);
internal static bool IsInvalidString(string val, out int validationFailureIndex)
{
@@ -157,7 +171,9 @@ namespace Jellyfin.SocketSharp
int len = val.Length;
if (len < 2)
+ {
return false;
+ }
char current = val[0];
for (int idx = 1; idx < len; idx++)
@@ -195,10 +211,15 @@ namespace Jellyfin.SocketSharp
bool IsContentType(string ct, bool starts_with)
{
- if (ct == null || ContentType == null) return false;
+ if (ct == null || ContentType == null)
+ {
+ return false;
+ }
if (starts_with)
+ {
return StrUtils.StartsWith(ContentType, ct, true);
+ }
return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase);
}
@@ -231,7 +252,9 @@ namespace Jellyfin.SocketSharp
break;
}
else
+ {
value.Append((char)c);
+ }
}
if (c == -1)
{
@@ -240,22 +263,26 @@ namespace Jellyfin.SocketSharp
}
}
else if (c == '&')
+ {
AddRawKeyValue(form, key, value);
+ }
else
+ {
key.Append((char)c);
+ }
}
if (c == -1)
+ {
AddRawKeyValue(form, key, value);
+ }
}
}
}
}
- void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value)
+ static void AddRawKeyValue(WebROCollection form, StringBuilder key, StringBuilder value)
{
- string decodedKey = WebUtility.UrlDecode(key.ToString());
- form.Add(decodedKey,
- WebUtility.UrlDecode(value.ToString()));
+ form.Add(WebUtility.UrlDecode(key.ToString()), WebUtility.UrlDecode(value.ToString()));
key.Length = 0;
value.Length = 0;
@@ -271,7 +298,9 @@ namespace Jellyfin.SocketSharp
foreach (var pair in this)
{
if (result.Length > 0)
+ {
result.Append('&');
+ }
var key = pair.Name;
if (key != null && key.Length > 0)
@@ -314,33 +343,52 @@ namespace Jellyfin.SocketSharp
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");
+ }
+
// reordered to avoid possible integer overflow
if (dest_offset > len - count)
+ {
throw new ArgumentException("Reading would overrun buffer");
+ }
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;
}
@@ -348,14 +396,20 @@ namespace Jellyfin.SocketSharp
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;
}
@@ -380,7 +434,9 @@ namespace Jellyfin.SocketSharp
long virt = real - offset;
if (virt < 0 || virt > Length)
+ {
throw new ArgumentException();
+ }
position = s.Seek(real, SeekOrigin.Begin);
return position;
@@ -410,7 +466,9 @@ namespace Jellyfin.SocketSharp
set
{
if (value > Length)
- throw new ArgumentOutOfRangeException();
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
position = Seek(value, SeekOrigin.Begin);
}
@@ -438,7 +496,7 @@ namespace Jellyfin.SocketSharp
public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture;
}
- internal sealed class StrUtils
+ internal static class StrUtils
{
public static bool StartsWith(string str1, string str2, bool ignore_case)
{
@@ -455,11 +513,15 @@ namespace Jellyfin.SocketSharp
{
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;
@@ -493,7 +555,7 @@ namespace Jellyfin.SocketSharp
Encoding encoding;
StringBuilder sb;
- const byte HYPHEN = (byte)'-', LF = (byte)'\n', CR = (byte)'\r';
+ const byte LF = (byte)'\n', CR = (byte)'\r';
// See RFC 2046
// In the case of multipart entities, in which one or more different
@@ -520,7 +582,7 @@ namespace Jellyfin.SocketSharp
sb = new StringBuilder();
}
- string ReadLine()
+ private string ReadLine()
{
// CRLF or LF are ok as line endings.
bool got_cr = false;
@@ -543,58 +605,86 @@ namespace Jellyfin.SocketSharp
}
if (got_cr)
+ {
sb.Length--;
+ }
return sb.ToString();
}
- static string GetContentDispositionAttribute(string l, string name)
+ private static string GetContentDispositionAttribute(string l, string name)
{
int idx = l.IndexOf(name + "=\"");
if (idx < 0)
+ {
return null;
+ }
+
int begin = idx + name.Length + "=\"".Length;
int end = l.IndexOf('"', begin);
if (end < 0)
+ {
return null;
+ }
+
if (begin == end)
- return "";
+ {
+ return string.Empty;
+ }
+
return l.Substring(begin, end - begin);
}
- string GetContentDispositionAttributeWithEncoding(string l, string name)
+ private string GetContentDispositionAttributeWithEncoding(string l, string name)
{
int idx = l.IndexOf(name + "=\"");
if (idx < 0)
+ {
return null;
+ }
+
int begin = idx + name.Length + "=\"".Length;
int end = l.IndexOf('"', begin);
if (end < 0)
+ {
return null;
+ }
+
if (begin == end)
- return "";
+ {
+ return string.Empty;
+ }
string temp = l.Substring(begin, end - begin);
byte[] source = new byte[temp.Length];
for (int i = temp.Length - 1; i >= 0; i--)
+ {
source[i] = (byte)temp[i];
+ }
return encoding.GetString(source, 0, source.Length);
}
- bool ReadBoundary()
+ private bool ReadBoundary()
{
try
{
string line = ReadLine();
- while (line == "")
+ while (line == string.Empty)
+ {
line = ReadLine();
+ }
+
if (line[0] != '-' || line[1] != '-')
+ {
return false;
+ }
if (!StrUtils.EndsWith(line, boundary, false))
+ {
return true;
+ }
}
catch
{
@@ -603,25 +693,31 @@ namespace Jellyfin.SocketSharp
return false;
}
- string ReadHeaders()
+ private string ReadHeaders()
{
string s = ReadLine();
- if (s == "")
+ if (s.Length == 0)
+ {
return null;
+ }
return s;
}
- bool CompareBytes(byte[] orig, byte[] other)
+ private static bool CompareBytes(byte[] orig, byte[] other)
{
for (int i = orig.Length - 1; i >= 0; i--)
+ {
if (orig[i] != other[i])
+ {
return false;
+ }
+ }
return true;
}
- long MoveToNextBoundary()
+ private long MoveToNextBoundary()
{
long retval = 0;
bool got_cr = false;
@@ -631,13 +727,18 @@ namespace Jellyfin.SocketSharp
while (true)
{
if (c == -1)
+ {
return -1;
+ }
if (state == 0 && c == LF)
{
retval = data.Position - 1;
if (got_cr)
+ {
retval--;
+ }
+
state = 1;
c = data.ReadByte();
}
@@ -650,7 +751,9 @@ namespace Jellyfin.SocketSharp
{
c = data.ReadByte();
if (c == -1)
+ {
return -1;
+ }
if (c != '-')
{
@@ -662,7 +765,9 @@ namespace Jellyfin.SocketSharp
int nread = data.Read(buffer, 0, buffer.Length);
int bl = buffer.Length;
if (nread != bl)
+ {
return -1;
+ }
if (!CompareBytes(boundary_bytes, buffer))
{
@@ -673,6 +778,7 @@ namespace Jellyfin.SocketSharp
data.Position++;
got_cr = false;
}
+
c = data.ReadByte();
continue;
}
@@ -690,12 +796,16 @@ namespace Jellyfin.SocketSharp
data.Position++;
got_cr = false;
}
+
c = data.ReadByte();
continue;
}
data.Position = retval + 2;
if (got_cr)
+ {
data.Position++;
+ }
+
break;
}
else
@@ -711,7 +821,9 @@ namespace Jellyfin.SocketSharp
public Element ReadNextElement()
{
if (at_eof || ReadBoundary())
+ {
return null;
+ }
var elem = new Element();
string header;
@@ -734,19 +846,27 @@ namespace Jellyfin.SocketSharp
elem.Start = start;
long pos = MoveToNextBoundary();
if (pos == -1)
+ {
return null;
+ }
elem.Length = pos - start;
return elem;
}
- static string StripPath(string path)
+ private static string StripPath(string path)
{
if (path == null || path.Length == 0)
+ {
return path;
+ }
- if (path.IndexOf(":\\") != 1 && !path.StartsWith("\\\\"))
+ if (path.IndexOf(":\\", StringComparison.Ordinal) != 1
+ && !path.StartsWith("\\\\", StringComparison.Ordinal))
+ {
return path;
+ }
+
return path.Substring(path.LastIndexOf('\\') + 1);
}
}