diff options
Diffstat (limited to 'Jellyfin.Server/SocketSharp/RequestMono.cs')
| -rw-r--r-- | Jellyfin.Server/SocketSharp/RequestMono.cs | 168 |
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); } } |
