using System; using System.Collections; using System.Collections.Generic; using System.IO; namespace UnityEngine { #if ENABLE_WWW partial class WWW { #if UNITY_WEBPLAYER || UNITY_EDITOR static readonly char[] forbiddenCharacters = { (char)0, (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, (char)31, (char)127 }; // From http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method static readonly string[] forbiddenHeaderKeys = { "Accept-Charset", "Accept-Encoding", "Access-Control-Request-Headers", "Access-Control-Request-Method", "Connection", "Content-Length", "Cookie", "Cookie2", "Date", "DNT", "Expect", "Host", "Keep-Alive", "Origin", "Referer", "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent", "Via", "X-Unity-Version", }; // Ensure headers do not contain invalid characters (ASCII 0-31, 127) // This prevents XSS and header-spoofing vulnerabilities. private static void CheckSecurityOnHeaders(string[] headers) { bool failNoisy = Application.GetBuildUnityVersion() >= Application.GetNumericUnityVersion("4.3.0b1"); // On non-webplayer platforms, we permit the platform itself to define the restrictions. for(int i = 0; i < headers.Length; i+=2) { // headers[i] is the header name // headers[i+1] is the header body foreach(string forbiddenHeaderKey in forbiddenHeaderKeys) { if(string.Equals(headers[i], forbiddenHeaderKey, StringComparison.CurrentCultureIgnoreCase)) { if(failNoisy) { throw new ArgumentException("Cannot overwrite header: " + headers[i]); } else { Debug.LogError("Illegal header overwrite, this will fail in 4.3 and above: " + headers[i]); } } } if(headers[i].StartsWith("Sec-") || headers[i].StartsWith("Proxy-")) { if(failNoisy) { throw new ArgumentException("Cannot overwrite header: " + headers[i]); } else { Debug.LogError("Illegal header overwrite, this will fail in 4.3 and above: " + headers[i]); } } if(headers[i].IndexOfAny(forbiddenCharacters) > -1 || headers[i+1].IndexOfAny(forbiddenCharacters) > -1) { if(failNoisy) { throw new ArgumentException("Cannot include control characters " + "in a HTTP header, either as key or value."); } else { Debug.LogError("Illegal control characters in header, this will fail in 4.3 and above"); } } } } #endif #if !UNITY_METRO_API && !UNITY_WP8_API private static string[] FlattenedHeadersFrom(Hashtable headers) { if (headers == null) return null; var flattenedHeaders = new string[headers.Count * 2]; var i = 0; foreach (DictionaryEntry entry in headers) { flattenedHeaders[i++] = entry.Key.ToString(); flattenedHeaders[i++] = entry.Value.ToString(); } return flattenedHeaders; } #else private static string[] FlattenedHeadersFrom(Dictionary headers) { if (headers == null) return null; var flattenedHeaders = new string[headers.Count * 2]; var i = 0; foreach (KeyValuePair entry in headers) { flattenedHeaders[i++] = entry.Key.ToString(); flattenedHeaders[i++] = entry.Value.ToString(); } return flattenedHeaders; } #endif #if ENABLE_GENERICS && !UNITY_WEBGL internal static Dictionary ParseHTTPHeaderString(string input) { if (input == null) throw new ArgumentException("input was null to ParseHTTPHeaderString"); var result = new Dictionary(); var reader = new StringReader(input); int count = 0; while (true) { var line = reader.ReadLine(); if (line == null) break; // The first line in the response header is the HTTP status line, according to the // HTTP 1.1 specification (http://tools.ietf.org/html/rfc2616#section-6). Lets save it. if (count++ == 0 && line.StartsWith("HTTP")) { result["STATUS"] = line; continue; } var index = line.IndexOf(": "); if (index == -1) continue; var key = line.Substring(0, index).ToUpper(); var value = line.Substring(index + 2); result[key] = value; } return result; } #endif } #endif }