| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204 |
- //
- // System.Web.HttpRequest.cs
- //
- //
- // Author:
- // Miguel de Icaza ([email protected])
- // Gonzalo Paniagua Javier ([email protected])
- // Marek Habersack <[email protected]>
- //
- //
- // Copyright (C) 2005-2010 Novell, Inc (http://www.novell.com)
- // Copyright (C) 2011-2012 Xamarin, Inc (http://xamarin.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System.Text;
- using System.Collections;
- using System.Collections.Specialized;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Security;
- using System.Security.Permissions;
- using System.Security.Principal;
- using System.Web.Configuration;
- using System.Web.Management;
- using System.Web.UI;
- using System.Web.Util;
- using System.Globalization;
- #if NET_4_0
- using System.Security.Authentication.ExtendedProtection;
- using System.Web.Routing;
- #endif
- namespace System.Web
- {
- // CAS - no InheritanceDemand here as the class is sealed
- [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
- public sealed partial class HttpRequest
- {
- HttpWorkerRequest worker_request;
- HttpContext context;
- WebROCollection query_string_nvc;
- //
- //string filename;
- string orig_url = null;
- UriBuilder url_components;
- string client_target;
- //
- // On-demand computed values
- //
- HttpBrowserCapabilities browser_capabilities;
- string file_path, base_virtual_dir, root_virtual_dir, client_file_path;
- string content_type;
- int content_length = -1;
- Encoding encoding;
- string current_exe_path;
- string physical_path;
- string unescaped_path;
- string original_path;
- string path_info;
- string raw_url;
- WebROCollection all_params;
- WebROCollection headers;
- Stream input_stream;
- InputFilterStream input_filter;
- Stream filter;
- HttpCookieCollection cookies;
- string http_method;
- WebROCollection form;
- HttpFileCollection files;
-
- ServerVariablesCollection server_variables;
- HttpClientCertificate client_cert;
-
- string request_type;
- string [] accept_types;
- string [] user_languages;
- Uri cached_url;
- TempFileStream request_file;
- readonly static System.Net.IPAddress [] host_addresses;
-
- // Validations
- bool validate_cookies, validate_query_string, validate_form;
- bool checked_cookies, checked_query_string, checked_form;
- static readonly UrlMappingCollection urlMappings;
- readonly static char [] queryTrimChars = {'?'};
- #if NET_4_0
- bool lazyFormValidation;
- bool lazyQueryStringValidation;
- bool inputValidationEnabled;
- RequestContext requestContext;
- BufferlessInputStream bufferlessInputStream;
-
- static bool validateRequestNewMode;
- internal static bool ValidateRequestNewMode {
- get { return validateRequestNewMode; }
- }
- internal bool InputValidationEnabled {
- get { return inputValidationEnabled; }
- }
-
- private static char[] RequestPathInvalidCharacters {
- get; set;
- }
- private static char[] CharsFromList (string list)
- {
- // List format is very strict and enforced by the Configuration
- // there must be a single char separated by commas with no trailing comma
- // whitespace is allowed though and should be trimmed.
-
- string [] pieces = list.Split (',');
- char [] chars = new char [pieces.Length];
- for (int i = 0; i < chars.Length; i++) {
- string trimmed = pieces [i].Trim ();
- if (trimmed.Length != 1) {
- // This should have been caught by System.Web.Configuration
- // and throw a configuration error. This is just here for sanity
- throw new System.Configuration.ConfigurationErrorsException ();
- }
- chars [i] = trimmed [0];
- }
- return chars;
- }
- #endif
- static HttpRequest ()
- {
- try {
- UrlMappingsSection ums = WebConfigurationManager.GetWebApplicationSection ("system.web/urlMappings") as UrlMappingsSection;
- if (ums != null && ums.IsEnabled) {
- urlMappings = ums.UrlMappings;
- if (urlMappings.Count == 0)
- urlMappings = null;
- }
- #if NET_4_0
- Version validationMode = HttpRuntime.Section.RequestValidationMode;
- if (validationMode >= new Version (4, 0)) {
- validateRequestNewMode = true;
- string invalidChars = HttpRuntime.Section.RequestPathInvalidCharacters;
- if (!String.IsNullOrEmpty (invalidChars))
- RequestPathInvalidCharacters = CharsFromList (invalidChars);
- }
- #endif
- } catch {
- // unlikely to happen
- }
-
- host_addresses = GetLocalHostAddresses ();
- }
-
- public HttpRequest (string filename, string url, string queryString)
- {
- // warning 169: what are we supposed to do with filename?
-
- //this.filename = filename;
- orig_url = url;
- url_components = new UriBuilder (url);
- url_components.Query = queryString;
-
- query_string_nvc = new WebROCollection ();
- if (queryString != null)
- HttpUtility.ParseQueryString (queryString, Encoding.Default, query_string_nvc);
- query_string_nvc.Protect ();
- }
- internal HttpRequest (HttpWorkerRequest worker_request, HttpContext context)
- {
- this.worker_request = worker_request;
- this.context = context;
- }
-
- internal UriBuilder UrlComponents {
- get {
- if (url_components == null) {
- string query;
- byte[] queryStringRaw = worker_request.GetQueryStringRawBytes();
- if(queryStringRaw != null)
- query = ContentEncoding.GetString(queryStringRaw);
- else
- query = worker_request.GetQueryString();
-
- BuildUrlComponents (ApplyUrlMapping (worker_request.GetUriPath ()), query);
- }
- return url_components;
- }
- }
- void BuildUrlComponents (string path, string query)
- {
- if (url_components != null)
- return;
- url_components = new UriBuilder ();
- url_components.Scheme = worker_request.GetProtocol ();
- url_components.Host = worker_request.GetServerName ();
- url_components.Port = worker_request.GetLocalPort ();
- url_components.Path = path;
- if (query != null && query.Length > 0)
- url_components.Query = query.TrimStart (queryTrimChars);
- }
- internal string ApplyUrlMapping (string url)
- {
- if (urlMappings == null)
- return url;
- string relUrl = VirtualPathUtility.ToAppRelative (url);
- UrlMapping um = null;
-
- foreach (UrlMapping u in urlMappings) {
- if (u == null)
- continue;
- if (String.Compare (relUrl, u.Url, StringComparison.Ordinal) == 0) {
- um = u;
- break;
- }
- }
- if (um == null)
- return url;
- string rawUrl = VirtualPathUtility.ToAbsolute (um.MappedUrl.Trim ());
- Uri newUrl = new Uri ("http://host.com" + rawUrl);
- if (url_components != null) {
- url_components.Path = newUrl.AbsolutePath;
- url_components.Query = newUrl.Query.TrimStart (queryTrimChars);
- query_string_nvc = new WebROCollection ();
- HttpUtility.ParseQueryString (newUrl.Query, Encoding.Default, query_string_nvc);
- query_string_nvc.Protect ();
- } else
- BuildUrlComponents (newUrl.AbsolutePath, newUrl.Query);
- return url_components.Path;
- }
- string [] SplitHeader (int header_index)
- {
- string [] result = null;
- string header = worker_request.GetKnownRequestHeader (header_index);
- if (header != null && header != "" && header.Trim () != "") {
- result = header.Split (',');
- for (int i = result.Length - 1; i >= 0; i--)
- result [i] = result [i].Trim ();
- }
- return result;
- }
- public string [] AcceptTypes {
- get {
- if (worker_request == null)
- return null;
- if (accept_types == null)
- accept_types = SplitHeader (HttpWorkerRequest.HeaderAccept);
- return accept_types;
- }
- }
- #if !TARGET_JVM
- public WindowsIdentity LogonUserIdentity {
- get { throw new NotImplementedException (); }
- }
- #endif
-
- string anonymous_id;
- public string AnonymousID {
- get {
- return anonymous_id;
- }
- internal set {
- anonymous_id = value;
- }
- }
- public string ApplicationPath {
- get {
- if (worker_request == null)
- return null;
- return worker_request.GetAppPath ();
- }
- }
- public HttpBrowserCapabilities Browser {
- get {
- if (browser_capabilities == null)
- #if NET_4_0
- browser_capabilities = HttpCapabilitiesBase.BrowserCapabilitiesProvider.GetBrowserCapabilities (this);
- #else
- browser_capabilities = (HttpBrowserCapabilities)
- HttpCapabilitiesBase.GetConfigCapabilities (null, this);
- #endif
- return browser_capabilities;
- }
- set {
- browser_capabilities = value;
- }
- }
- internal bool BrowserMightHaveSpecialWriter {
- get {
- return (browser_capabilities != null
- || HttpApplicationFactory.AppBrowsersFiles.Length > 0);
- }
- }
- internal bool BrowserMightHaveAdapters {
- get {
- return (browser_capabilities != null
- || HttpApplicationFactory.AppBrowsersFiles.Length > 0);
- }
- }
- public HttpClientCertificate ClientCertificate {
- get {
- if (client_cert == null)
- client_cert = new HttpClientCertificate (worker_request);
- return client_cert;
- }
- }
- static internal string GetParameter (string header, string attr)
- {
- 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);
- }
- public Encoding ContentEncoding {
- get {
- if (encoding == null){
- if (worker_request == null)
- throw HttpException.NewWithCode ("No HttpWorkerRequest", WebEventCodes.RuntimeErrorRequestAbort);
-
- string content_type = ContentType;
- string parameter = GetParameter (content_type, "; charset=");
- if (parameter == null) {
- encoding = WebEncoding.RequestEncoding;
- } else {
- try {
- // Do what the #1 web server does
- encoding = Encoding.GetEncoding (parameter);
- } catch {
- encoding = WebEncoding.RequestEncoding;
- }
- }
- }
- return encoding;
- }
- set {
- encoding = value;
- }
- }
- public int ContentLength {
- get {
- if (content_length == -1){
- if (worker_request == null)
- return 0;
- string cl = worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderContentLength);
- if (cl != null) {
- try {
- content_length = Int32.Parse (cl);
- } catch { }
- }
- }
- // content_length will still be < 0, but we know we gotta read from the client
- if (content_length < 0)
- return 0;
- return content_length;
- }
- }
- public string ContentType {
- get {
- if (content_type == null){
- if (worker_request != null)
- content_type = worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderContentType);
- if (content_type == null)
- content_type = String.Empty;
- }
-
- return content_type;
- }
- set {
- content_type = value;
- }
- }
- public HttpCookieCollection Cookies {
- get {
- if (cookies == null) {
- if (worker_request == null) {
- cookies = new HttpCookieCollection ();
- } else {
- string cookie_hv = worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderCookie);
- cookies = new HttpCookieCollection (cookie_hv);
- }
- }
- #if TARGET_J2EE
- // For J2EE portal support we emulate cookies using the session.
- GetSessionCookiesForPortal (cookies);
- #endif
- bool needValidation = validate_cookies;
- #if NET_4_0
- needValidation |= validateRequestNewMode;
- #endif
- if (needValidation && !checked_cookies) {
- // Setting this before calling the validator prevents
- // possible endless recursion
- checked_cookies = true;
- ValidateCookieCollection (cookies);
- }
- return cookies;
- }
- }
- public string CurrentExecutionFilePath {
- get {
- if (current_exe_path != null)
- return current_exe_path;
- return FilePath;
- }
- }
- #if NET_4_0
- public string CurrentExecutionFilePathExtension {
- get { return global::System.IO.Path.GetExtension (CurrentExecutionFilePath); }
- }
- #endif
- public string AppRelativeCurrentExecutionFilePath {
- get {
- return VirtualPathUtility.ToAppRelative (CurrentExecutionFilePath);
- }
- }
- public string FilePath {
- get {
- if (worker_request == null)
- return "/"; // required for 2.0
- if (file_path == null)
- file_path = UrlUtils.Canonic (ApplyUrlMapping (worker_request.GetFilePath ()));
- return file_path;
- }
- }
- internal string ClientFilePath {
- get {
- if (client_file_path == null) {
- if (worker_request == null)
- return "/";
-
- return UrlUtils.Canonic (ApplyUrlMapping (worker_request.GetFilePath ()));
- }
-
- return client_file_path;
- }
- set {
- if (value == null || value.Length == 0)
- client_file_path = null;
- else
- client_file_path = value;
- }
- }
-
- internal string BaseVirtualDir {
- get {
- if (base_virtual_dir == null){
- base_virtual_dir = FilePath;
- if (UrlUtils.HasSessionId (base_virtual_dir))
- base_virtual_dir = UrlUtils.RemoveSessionId (VirtualPathUtility.GetDirectory (base_virtual_dir), base_virtual_dir);
-
- int p = base_virtual_dir.LastIndexOf ('/');
- if (p != -1) {
- if (p == 0)
- p = 1;
- base_virtual_dir = base_virtual_dir.Substring (0, p);
- } else
- base_virtual_dir = "/";
- }
- return base_virtual_dir;
- }
- }
-
- public HttpFileCollection Files {
- get {
- if (files == null) {
- files = new HttpFileCollection ();
- if ((worker_request != null) && IsContentType ("multipart/form-data", true)) {
- form = new WebROCollection ();
- LoadMultiPart ();
- form.Protect ();
- }
- }
- return files;
- }
- }
- public Stream Filter {
- get {
- if (filter != null)
- return filter;
- if (input_filter == null)
- input_filter = new InputFilterStream ();
- return input_filter;
- }
- set {
- // This checks that get_ was called before.
- if (input_filter == null)
- throw new HttpException ("Invalid filter");
- filter = value;
- }
- }
- // GetSubStream returns a 'copy' of the InputStream with Position set to 0.
- static Stream GetSubStream (Stream stream)
- {
- #if !TARGET_JVM
- if (stream is IntPtrStream)
- return new IntPtrStream (stream);
- #endif
- if (stream is MemoryStream) {
- MemoryStream other = (MemoryStream) stream;
- return new MemoryStream (other.GetBuffer (), 0, (int) other.Length, false, true);
- }
- if (stream is TempFileStream) {
- ((TempFileStream) stream).SavePosition ();
- return stream;
- }
- throw new NotSupportedException ("The stream is " + stream.GetType ());
- }
- static void EndSubStream (Stream stream)
- {
- if (stream is TempFileStream) {
- ((TempFileStream) stream).RestorePosition ();
- }
- }
- //
- // Loads the data on the form for multipart/form-data
- //
- void LoadMultiPart ()
- {
- string boundary = GetParameter (ContentType, "; boundary=");
- if (boundary == null)
- return;
- Stream input = GetSubStream (InputStream);
- HttpMultipart multi_part = new HttpMultipart (input, boundary, ContentEncoding);
- HttpMultipart.Element e;
- while ((e = multi_part.ReadNextElement ()) != null) {
- if (e.Filename == null){
- byte [] copy = new byte [e.Length];
-
- input.Position = e.Start;
- input.Read (copy, 0, (int) e.Length);
- form.Add (e.Name, ContentEncoding.GetString (copy));
- } else {
- //
- // We use a substream, as in 2.x we will support large uploads streamed to disk,
- //
- HttpPostedFile sub = new HttpPostedFile (e.Filename, e.ContentType, input, e.Start, e.Length);
- files.AddFile (e.Name, sub);
- }
- }
- EndSubStream (input);
- }
- //
- // Adds the key/value to the form, and sets the argumets to empty
- //
- void AddRawKeyValue (StringBuilder key, StringBuilder value)
- {
- string decodedKey = HttpUtility.UrlDecode (key.ToString (), ContentEncoding);
- form.Add (decodedKey,
- HttpUtility.UrlDecode (value.ToString (), ContentEncoding));
- key.Length = 0;
- value.Length = 0;
- }
- //
- // Loads the form data from on a application/x-www-form-urlencoded post
- //
- #if TARGET_J2EE
- void RawLoadWwwForm ()
- #else
- void LoadWwwForm ()
- #endif
- {
- using (Stream input = GetSubStream (InputStream)) {
- using (StreamReader s = new StreamReader (input, ContentEncoding)) {
- StringBuilder key = new StringBuilder ();
- StringBuilder value = new StringBuilder ();
- int c;
- while ((c = s.Read ()) != -1){
- if (c == '='){
- value.Length = 0;
- while ((c = s.Read ()) != -1){
- if (c == '&'){
- AddRawKeyValue (key, value);
- break;
- } else
- value.Append ((char) c);
- }
- if (c == -1){
- AddRawKeyValue (key, value);
- return;
- }
- } else if (c == '&')
- AddRawKeyValue (key, value);
- else
- key.Append ((char) c);
- }
- if (c == -1)
- AddRawKeyValue (key, value);
- EndSubStream (input);
- }
- }
- }
- bool IsContentType (string ct, bool starts_with)
- {
- if (starts_with)
- return StrUtils.StartsWith (ContentType, ct, true);
- return String.Compare (ContentType, ct, true, Helpers.InvariantCulture) == 0;
- }
- internal WebROCollection FormUnvalidated {
- get {
- if (form == null){
- form = new WebROCollection ();
- files = new HttpFileCollection ();
- if (IsContentType ("multipart/form-data", true))
- LoadMultiPart ();
- else if (
- IsContentType ("application/x-www-form-urlencoded", true))
- LoadWwwForm ();
- form.Protect ();
- }
- return form;
- }
- }
-
- public NameValueCollection Form {
- get {
- NameValueCollection form = FormUnvalidated;
- #if NET_4_0
- if (validateRequestNewMode && !checked_form) {
- if (!lazyFormValidation) {
- // Setting this before calling the validator prevents
- // possible endless recursion
- checked_form = true;
- ValidateNameValueCollection ("Form", form, RequestValidationSource.Form);
- }
- } else
- #endif
- if (validate_form && !checked_form){
- checked_form = true;
- ValidateNameValueCollection ("Form", form);
- }
-
- return form;
- }
- }
- public NameValueCollection Headers {
- get {
- if (headers == null) {
- headers = new HeadersCollection (this);
- #if NET_4_0
- if (validateRequestNewMode) {
- RequestValidator validator = RequestValidator.Current;
- int validationFailureIndex;
- foreach (string hkey in headers.AllKeys) {
- string value = headers [hkey];
-
- if (!validator.IsValidRequestString (HttpContext.Current, value, RequestValidationSource.Headers, hkey, out validationFailureIndex))
- ThrowValidationException ("Headers", hkey, value);
- }
- }
- #endif
- }
-
- return headers;
- }
- }
- public string HttpMethod {
- get {
- if (http_method == null){
- if (worker_request != null)
- http_method = worker_request.GetHttpVerbName ();
- else
- http_method = "GET";
- }
- return http_method;
- }
- }
- void DoFilter (byte [] buffer)
- {
- if (input_filter == null || filter == null)
- return;
- if (buffer.Length < 1024)
- buffer = new byte [1024];
- // Replace the input with the filtered input
- input_filter.BaseStream = input_stream;
- MemoryStream ms = new MemoryStream ();
- while (true) {
- int n = filter.Read (buffer, 0, buffer.Length);
- if (n <= 0)
- break;
- ms.Write (buffer, 0, n);
- }
- // From now on input_stream has the filtered input
- input_stream = new MemoryStream (ms.GetBuffer (), 0, (int) ms.Length, false, true);
- }
- #if !TARGET_JVM
- const int INPUT_BUFFER_SIZE = 32*1024;
- TempFileStream GetTempStream ()
- {
- string tempdir = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
- TempFileStream f = null;
- string path;
- Random rnd = new Random ();
- int num;
- do {
- num = rnd.Next ();
- num++;
- path = System.IO.Path.Combine (tempdir, "tmp" + num.ToString("x") + ".req");
- try {
- f = new TempFileStream (path);
- } catch (SecurityException) {
- // avoid an endless loop
- throw;
- } catch { }
- } while (f == null);
- return f;
- }
- void MakeInputStream ()
- {
- if (input_stream != null)
- return;
- if (worker_request == null) {
- input_stream = new MemoryStream (new byte [0], 0, 0, false, true);
- DoFilter (new byte [1024]);
- return;
- }
- //
- // Use an unmanaged memory block as this might be a large
- // upload
- //
- int content_length = ContentLength;
- int content_length_kb = content_length / 1024;
- HttpRuntimeSection config = HttpRuntime.Section;
- if (content_length_kb > config.MaxRequestLength)
- throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge);
- int total = 0;
- byte [] buffer;
- buffer = worker_request.GetPreloadedEntityBody ();
- // we check the instance field 'content_length' here, not the local var.
- if (this.content_length <= 0 || worker_request.IsEntireEntityBodyIsPreloaded ()) {
- if (buffer == null || content_length == 0) {
- input_stream = new MemoryStream (new byte [0], 0, 0, false, true);
- } else {
- input_stream = new MemoryStream (buffer, 0, buffer.Length, false, true);
- }
- DoFilter (new byte [1024]);
- return;
- }
- if (buffer != null)
- total = buffer.Length;
- if (content_length > 0 && content_length_kb >= config.RequestLengthDiskThreshold) {
- // Writes the request to disk
- total = Math.Min (content_length, total);
- request_file = GetTempStream ();
- Stream output = request_file;
- if (total > 0)
- output.Write (buffer, 0, total);
- if (total < content_length) {
- buffer = new byte [Math.Min (content_length, INPUT_BUFFER_SIZE)];
- do {
- int n;
- int min = Math.Min (content_length - total, INPUT_BUFFER_SIZE);
- n = worker_request.ReadEntityBody (buffer, min);
- if (n <= 0)
- break;
- output.Write (buffer, 0, n);
- total += n;
- } while (total < content_length);
- }
- request_file.SetReadOnly ();
- input_stream = request_file;
- } else if (content_length > 0) {
- // Buffers the request in an IntPtrStream
- total = Math.Min (content_length, total);
- IntPtr content = Marshal.AllocHGlobal (content_length);
- if (content == (IntPtr) 0)
- throw HttpException.NewWithCode (
- String.Format ("Not enough memory to allocate {0} bytes.", content_length),
- WebEventCodes.WebErrorOtherError);
- if (total > 0)
- Marshal.Copy (buffer, 0, content, total);
- if (total < content_length) {
- buffer = new byte [Math.Min (content_length, INPUT_BUFFER_SIZE)];
- do {
- int n;
- int min = Math.Min (content_length - total, INPUT_BUFFER_SIZE);
- n = worker_request.ReadEntityBody (buffer, min);
- if (n <= 0)
- break;
- Marshal.Copy (buffer, 0, (IntPtr) ((long)content + total), n);
- total += n;
- } while (total < content_length);
- }
- input_stream = new IntPtrStream (content, total);
- } else {
- // Buffers the request in a MemoryStream or writes to disk if threshold exceeded
- MemoryStream ms = new MemoryStream ();
- Stream output = ms;
- if (total > 0)
- ms.Write (buffer, 0, total);
- buffer = new byte [INPUT_BUFFER_SIZE];
- long maxlength = config.MaxRequestLength * 1024L;
- long disk_th = config.RequestLengthDiskThreshold * 1024L;
- int n;
- while (true) {
- n = worker_request.ReadEntityBody (buffer, INPUT_BUFFER_SIZE);
- if (n <= 0)
- break;
- total += n;
- if (total < 0 || total > maxlength)
- throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge);
- if (ms != null && total > disk_th) {
- // Swith to on-disk file.
- request_file = GetTempStream ();
- ms.WriteTo (request_file);
- ms = null;
- output = request_file;
- }
- output.Write (buffer, 0, n);
- }
- if (ms != null) {
- input_stream = new MemoryStream (ms.GetBuffer (), 0, (int) ms.Length, false, true);
- } else {
- request_file.SetReadOnly ();
- input_stream = request_file;
- }
- }
- DoFilter (buffer);
- if (total < content_length)
- throw HttpException.NewWithCode (411, "The request body is incomplete.", WebEventCodes.WebErrorOtherError);
- }
- #endif
- internal void ReleaseResources ()
- {
- Stream stream;
- if (input_stream != null){
- stream = input_stream;
- input_stream = null;
- try {
- stream.Close ();
- } catch {}
- }
- if (request_file != null) {
- stream = request_file;
- request_file = null;
- try {
- stream.Close ();
- } catch {}
- }
- }
- #if NET_4_0
- public RequestContext RequestContext {
- get {
- if (requestContext == null)
- requestContext = new RequestContext (new HttpContextWrapper (this.context ?? HttpContext.Current), new RouteData ());
- return requestContext;
- }
-
- internal set { requestContext = value; }
- }
- public ChannelBinding HttpChannelBinding {
- get {
- throw new PlatformNotSupportedException ("This property is not supported.");
- }
- }
- public Stream GetBufferlessInputStream ()
- {
- if (bufferlessInputStream == null) {
- if (input_stream != null)
- throw new HttpException ("Input stream has already been created");
- // we don't need to hook up the filter here, because the raw stream should be returned
- bufferlessInputStream = new BufferlessInputStream (this);
- }
- return bufferlessInputStream;
- }
- //
- // Stream that returns the data as it is read, without buffering
- //
- class BufferlessInputStream : Stream {
- HttpRequest request;
- // cached, the request content-length
- int content_length;
- // buffer that holds preloaded data
- byte [] preloadedBuffer;
- // indicates if we already served the whole preloaded buffer
- bool preloaded_served;
- // indicates if we already checked the request content-length against httpRuntime limit
- bool checked_maxRequestLength;
- // our stream position
- long position;
- //
- // @request: the containing request that created us, used to find out content length
- public BufferlessInputStream (HttpRequest request)
- {
- this.request = request;
- content_length = request.ContentLength;
- }
- public override bool CanRead {
- get { return true; }
- }
- public override bool CanSeek {
- get { return false; }
- }
- public override bool CanWrite {
- get { return false; }
- }
- public override long Length {
- get {
- return content_length;
- }
- }
- public override long Position {
- get {
- return position;
- }
- set {
- throw new NotSupportedException ("This is a readonly stream");
- }
- }
- public override void Flush ()
- {
- }
- public override int Read (byte [] buffer, int offset, int count)
- {
- if (buffer == null)
- throw new ArgumentNullException ("buffer");
- if (offset < 0 || count < 0)
- throw new ArgumentOutOfRangeException ("offset or count less than zero.");
- if (buffer.Length - offset < count )
- throw new ArgumentException ("offset+count",
- "The size of the buffer is less than offset + count.");
- if (count == 0 || request.worker_request == null)
- return 0;
- if (!checked_maxRequestLength) {
- int content_length_kb = content_length / 1024;
- HttpRuntimeSection config = HttpRuntime.Section;
- if (content_length_kb > config.MaxRequestLength)
- throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge);
- else
- checked_maxRequestLength = true;
- }
- // Serve the bytes we might have preloaded already.
- if (!preloaded_served) {
- if (preloadedBuffer == null)
- preloadedBuffer = request.worker_request.GetPreloadedEntityBody ();
- if (preloadedBuffer != null) {
- long bytes_left = preloadedBuffer.Length-position;
- int n = (int) Math.Min (count, bytes_left);
- Array.Copy (preloadedBuffer, position, buffer, offset, n);
- position += n;
- if (n == bytes_left)
- preloaded_served = true;
- return n;
- }
- else
- preloaded_served = true;
- }
- // serve bytes from worker request if available
- if (position < content_length) {
- long bytes_left = content_length-position;
- int n = count;
- if (bytes_left < count)
- n = (int) bytes_left;
- int bytes_read = request.worker_request.ReadEntityBody (buffer, offset, n);
- position += bytes_read;
- return bytes_read;
- }
- return 0;
- }
- public override long Seek (long offset, SeekOrigin origin)
- {
- throw new NotSupportedException ("Can not seek on the HttpRequest.BufferlessInputStream");
- }
- public override void SetLength (long value)
- {
- throw new NotSupportedException ("Can not set length on the HttpRequest.BufferlessInputStream");
- }
- public override void Write (byte [] buffer, int offset, int count)
- {
- throw new NotSupportedException ("Can not write on the HttpRequest.BufferlessInputStream");
- }
- //
- // TODO: explicitly support the async methods if there is a convenient way of doing it
- //
- }
- #endif
- public Stream InputStream {
- get {
- if (input_stream == null)
- MakeInputStream ();
- return input_stream;
- }
- }
- public bool IsAuthenticated {
- get {
- if (context.User == null || context.User.Identity == null)
- return false;
- return context.User.Identity.IsAuthenticated;
- }
- }
- public bool IsSecureConnection {
- get {
- if (worker_request == null)
- return false;
- return worker_request.IsSecure ();
- }
- }
- public string this [string key] {
- [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
- get {
- // "The QueryString, Form, Cookies, or ServerVariables collection member
- // specified in the key parameter."
- string val = QueryString [key];
- if (val == null)
- val = Form [key];
- if (val == null) {
- HttpCookie cookie = Cookies [key];
- if (cookie != null)
- val = cookie.Value;
- }
- if (val == null)
- val = ServerVariables [key];
- return val;
- }
- }
- public NameValueCollection Params {
- [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
- get {
- if (all_params == null)
- all_params = new HttpParamsCollection (QueryString, Form, ServerVariables, Cookies);
- return all_params;
- }
- }
- internal string PathNoValidation {
- get {
- if (original_path == null) {
- if (url_components != null)
- // use only if it's already been instantiated, so that we can't go into endless
- // recursion in some scenarios
- original_path = UrlComponents.Path;
- else
- original_path = ApplyUrlMapping (worker_request.GetUriPath ());
- }
- return original_path;
- }
- }
-
- public string Path {
- get {
- if (unescaped_path == null) {
- unescaped_path = PathNoValidation;
- #if NET_4_0
- if (validateRequestNewMode) {
- RequestValidator validator = RequestValidator.Current;
- int validationFailureIndex;
-
- if (!validator.IsValidRequestString (HttpContext.Current, unescaped_path, RequestValidationSource.Path, null, out validationFailureIndex))
- ThrowValidationException ("Path", "Path", unescaped_path);
- }
- #endif
- }
-
- return unescaped_path;
- }
- }
- public string PathInfo {
- get {
- if (path_info == null) {
- if (worker_request == null)
- return String.Empty;
- path_info = worker_request.GetPathInfo () ?? String.Empty;
- #if NET_4_0
- if (validateRequestNewMode) {
- RequestValidator validator = RequestValidator.Current;
- int validationFailureIndex;
-
- if (!validator.IsValidRequestString (HttpContext.Current, path_info, RequestValidationSource.PathInfo, null, out validationFailureIndex))
- ThrowValidationException ("PathInfo", "PathInfo", path_info);
- }
- #endif
- }
- return path_info;
- }
- }
- public string PhysicalApplicationPath {
- get {
- if (worker_request == null)
- throw new ArgumentNullException (); // like 2.0, 1.x throws TypeInitializationException
- string path = HttpRuntime.AppDomainAppPath;
- if (SecurityManager.SecurityEnabled) {
- new FileIOPermission (FileIOPermissionAccess.PathDiscovery, path).Demand ();
- }
- return path;
- }
- }
- public string PhysicalPath {
- get {
- if (worker_request == null)
- return String.Empty; // don't check security with an empty string!
- if (physical_path == null) {
- // Don't call HttpRequest.MapPath here, as that one *trims* the input
- physical_path = worker_request.MapPath (FilePath);
- }
- if (SecurityManager.SecurityEnabled) {
- new FileIOPermission (FileIOPermissionAccess.PathDiscovery, physical_path).Demand ();
- }
- return physical_path;
- }
- }
- internal string RootVirtualDir {
- get {
- if (root_virtual_dir == null){
- string fp = FilePath;
- int p = fp.LastIndexOf ('/');
- if (p < 1)
- root_virtual_dir = "/";
- else
- root_virtual_dir = fp.Substring (0, p);
- }
- return root_virtual_dir;
- }
- }
- internal WebROCollection QueryStringUnvalidated {
- get {
- if (query_string_nvc == null) {
- query_string_nvc = new WebROCollection ();
- string q = UrlComponents.Query;
- if (q != null) {
- if (q.Length != 0)
- q = q.Remove(0, 1);
-
- HttpUtility.ParseQueryString (q, ContentEncoding, query_string_nvc);
- }
-
- query_string_nvc.Protect();
- }
- return query_string_nvc;
- }
- }
-
- public NameValueCollection QueryString {
- get {
- NameValueCollection query_string_nvc = QueryStringUnvalidated;
- #if NET_4_0
- if (validateRequestNewMode && !checked_query_string) {
- if (!lazyQueryStringValidation) {
- // Setting this before calling the validator prevents
- // possible endless recursion
- checked_query_string = true;
- ValidateNameValueCollection ("QueryString", query_string_nvc, RequestValidationSource.QueryString);
- }
- } else
- #endif
- if (validate_query_string && !checked_query_string) {
- // Setting this before calling the validator prevents
- // possible endless recursion
- checked_query_string = true;
- ValidateNameValueCollection ("QueryString", query_string_nvc);
- }
-
- return query_string_nvc;
- }
- }
- public string RawUrl {
- get {
- if (raw_url == null) {
- if (worker_request != null)
- raw_url = worker_request.GetRawUrl ();
- else
- raw_url = UrlComponents.Path + UrlComponents.Query;
-
- if (raw_url == null)
- raw_url = String.Empty;
- #if NET_4_0
- if (validateRequestNewMode) {
- RequestValidator validator = RequestValidator.Current;
- int validationFailureIndex;
- if (!validator.IsValidRequestString (HttpContext.Current, raw_url, RequestValidationSource.RawUrl, null, out validationFailureIndex))
- ThrowValidationException ("RawUrl", "RawUrl", raw_url);
- }
- #endif
- }
-
- return raw_url;
- }
- }
- //
- // "GET" or "SET"
- //
- public string RequestType {
- get {
- if (request_type == null){
- if (worker_request != null) {
- request_type = worker_request.GetHttpVerbName ();
- http_method = request_type;
- } else {
- request_type = "GET";
- }
- }
- return request_type;
- }
- set {
- request_type = value;
- }
- }
- public NameValueCollection ServerVariables {
- [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Low)]
- get {
- if (server_variables == null)
- server_variables = new ServerVariablesCollection (this);
- return server_variables;
- }
- }
- public int TotalBytes {
- get {
- Stream ins = InputStream;
- return (int) ins.Length;
- }
- }
- public Uri Url {
- get {
- if (cached_url == null) {
- if (orig_url == null)
- cached_url = UrlComponents.Uri;
- else
- cached_url = new Uri (orig_url);
- }
- return cached_url;
- }
- }
- public Uri UrlReferrer {
- get {
- if (worker_request == null)
- return null;
- string hr = worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderReferer);
- if (hr == null)
- return null;
- Uri uri = null;
- try {
- uri = new Uri (hr);
- } catch (UriFormatException) {}
- return uri;
- }
- }
- public string UserAgent {
- get {
- if (worker_request == null)
- return null;
- return worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderUserAgent);
- }
- }
- public string UserHostAddress {
- get {
- if (worker_request == null)
- return null;
- return worker_request.GetRemoteAddress ();
- }
- }
- public string UserHostName {
- get {
- if (worker_request == null)
- return null;
- return worker_request.GetRemoteName ();
- }
- }
- public string [] UserLanguages {
- get {
- if (worker_request == null)
- return null;
- if (user_languages == null)
- user_languages = SplitHeader (HttpWorkerRequest.HeaderAcceptLanguage);
- return user_languages;
- }
- }
- public byte [] BinaryRead (int count)
- {
- if (count < 0)
- throw new ArgumentException ("count is < 0");
- Stream s = InputStream;
- byte [] ret = new byte [count];
- if (s.Read (ret, 0, count) != count)
- throw new ArgumentException (
- String.Format ("count {0} exceeds length of available input {1}",
- count, s.Length - s.Position));
- return ret;
- }
- public int [] MapImageCoordinates (string imageFieldName)
- {
- string method = HttpMethod;
- NameValueCollection coll = null;
- if (method == "HEAD" || method == "GET")
- coll = QueryString;
- else if (method == "POST")
- coll = Form;
- if (coll == null)
- return null;
- string x = coll [imageFieldName + ".x"];
- if (x == null || x == "")
- return null;
- string y = coll [imageFieldName + ".y"];
- if (y == null || y == "")
- return null;
- int [] result = new int [2];
- try {
- result [0] = Int32.Parse (x);
- result [1] = Int32.Parse (y);
- } catch {
- return null;
- }
- return result;
- }
- public string MapPath (string virtualPath)
- {
- if (worker_request == null)
- return null;
- return MapPath (virtualPath, BaseVirtualDir, true);
- }
- public string MapPath (string virtualPath, string baseVirtualDir, bool allowCrossAppMapping)
- {
- if (worker_request == null)
- throw HttpException.NewWithCode ("No HttpWorkerRequest", WebEventCodes.RuntimeErrorRequestAbort);
- if (virtualPath == null)
- virtualPath = "~";
- else {
- virtualPath = virtualPath.Trim ();
- if (virtualPath.Length == 0)
- virtualPath = "~";
- }
- if (!VirtualPathUtility.IsValidVirtualPath (virtualPath))
- throw HttpException.NewWithCode (String.Format ("'{0}' is not a valid virtual path.", virtualPath), WebEventCodes.RuntimeErrorRequestAbort);
- string appVirtualPath = HttpRuntime.AppDomainAppVirtualPath;
- if (!VirtualPathUtility.IsRooted (virtualPath)) {
- if (StrUtils.IsNullOrEmpty (baseVirtualDir))
- baseVirtualDir = appVirtualPath;
- virtualPath = VirtualPathUtility.Combine (VirtualPathUtility.AppendTrailingSlash (baseVirtualDir), virtualPath);
- if (!VirtualPathUtility.IsAbsolute (virtualPath))
- virtualPath = VirtualPathUtility.ToAbsolute (virtualPath, false);
- } else if (!VirtualPathUtility.IsAbsolute (virtualPath))
- virtualPath = VirtualPathUtility.ToAbsolute (virtualPath, false);
- bool isAppVirtualPath = String.Compare (virtualPath, appVirtualPath, RuntimeHelpers.StringComparison) == 0;
- appVirtualPath = VirtualPathUtility.AppendTrailingSlash (appVirtualPath);
- if (!allowCrossAppMapping){
- if (!StrUtils.StartsWith (virtualPath, appVirtualPath, true))
- throw new ArgumentException ("MapPath: Mapping across applications not allowed");
- if (appVirtualPath.Length > 1 && virtualPath.Length > 1 && virtualPath [0] != '/')
- throw HttpException.NewWithCode ("MapPath: Mapping across applications not allowed", WebEventCodes.RuntimeErrorRequestAbort);
- }
-
- if (!isAppVirtualPath && !virtualPath.StartsWith (appVirtualPath, RuntimeHelpers.StringComparison))
- throw new InvalidOperationException (String.Format ("Failed to map path '{0}'", virtualPath));
- #if TARGET_JVM
- return worker_request.MapPath (virtualPath);
- #else
- string path = worker_request.MapPath (virtualPath);
- if (virtualPath [virtualPath.Length - 1] != '/' && path [path.Length - 1] == System.IO.Path.DirectorySeparatorChar)
- path = path.TrimEnd (System.IO.Path.DirectorySeparatorChar);
- return path;
- #endif
- }
- public void SaveAs (string filename, bool includeHeaders)
- {
- Stream output = new FileStream (filename, FileMode.Create);
- if (includeHeaders) {
- StringBuilder sb = new StringBuilder ();
- string version = String.Empty;
- string path = "/";
- if (worker_request != null) {
- version = worker_request.GetHttpVersion ();
- path = UrlComponents.Path;
- }
- string qs = UrlComponents.Query;
- sb.AppendFormat ("{0} {1}{2} {3}\r\n", HttpMethod, path, qs, version);
- NameValueCollection coll = Headers;
- foreach (string k in coll.AllKeys) {
- sb.Append (k);
- sb.Append (':');
- sb.Append (coll [k]);
- sb.Append ("\r\n");
- }
- sb.Append ("\r\n");
- // latin1
- byte [] bytes = Encoding.GetEncoding (28591).GetBytes (sb.ToString ());
- output.Write (bytes, 0, bytes.Length);
- }
- // More than 1 call to SaveAs works fine on MS, so we "copy" the stream
- // to keep InputStream in its state.
- Stream input = GetSubStream (InputStream);
- try {
- long len = input.Length;
- int buf_size = (int) Math.Min ((len < 0 ? 0 : len), 8192);
- byte [] data = new byte [buf_size];
- int count = 0;
- while (len > 0 && (count = input.Read (data, 0, buf_size)) > 0) {
- output.Write (data, 0, count);
- len -= count;
- }
- } finally {
- output.Flush ();
- output.Close ();
- EndSubStream (input);
- }
- }
- public void ValidateInput ()
- {
- validate_cookies = true;
- validate_query_string = true;
- validate_form = true;
- #if NET_4_0
- inputValidationEnabled = true;
- #endif
- }
- #if NET_4_0
- internal void Validate ()
- {
- var cfg = HttpRuntime.Section;
- string query = UrlComponents.Query;
-
- if (query != null && query.Length > cfg.MaxQueryStringLength)
- throw new HttpException (400, "The length of the query string for this request exceeds the configured maxQueryStringLength value.");
-
- string path = PathNoValidation;
- if (path != null) {
- if (path.Length > cfg.MaxUrlLength)
- throw new HttpException (400, "The length of the URL for this request exceeds the configured maxUrlLength value.");
-
- char[] invalidChars = RequestPathInvalidCharacters;
- if (invalidChars != null) {
- int idx = path.IndexOfAny (invalidChars);
- if (idx != -1)
- throw HttpException.NewWithCode (
- String.Format ("A potentially dangerous Request.Path value was detected from the client ({0}).", path [idx]),
- WebEventCodes.RuntimeErrorValidationFailure
- );
- }
- }
- if (validateRequestNewMode)
- ValidateInput ();
- }
- #endif
- #region internal routines
- internal string ClientTarget {
- get {
- return client_target;
- }
- set {
- client_target = value;
- }
- }
-
- public bool IsLocal {
- get {
- string address = worker_request.GetRemoteAddress ();
- if (StrUtils.IsNullOrEmpty (address))
- return false;
- if (address == "127.0.0.1")
- return true;
- System.Net.IPAddress remoteAddr = System.Net.IPAddress.Parse (address);
- if (System.Net.IPAddress.IsLoopback (remoteAddr))
- return true;
- for (int i = 0; i < host_addresses.Length; i++)
- if (remoteAddr.Equals (host_addresses [i]))
- return true;
- return false;
- }
- }
- internal void SetFilePath (string path)
- {
- file_path = path;
- physical_path = null;
- original_path = null;
- }
- internal void SetCurrentExePath (string path)
- {
- cached_url = null;
- current_exe_path = path;
- UrlComponents.Path = path + PathInfo;
- // recreated on demand
- root_virtual_dir = null;
- base_virtual_dir = null;
- physical_path = null;
- unescaped_path = null;
- original_path = null;
- }
- internal void SetPathInfo (string pi)
- {
- cached_url = null;
- path_info = pi;
- original_path = null;
- string path = UrlComponents.Path;
- UrlComponents.Path = path + PathInfo;
- }
- #if NET_4_0
- internal void SetFormCollection (WebROCollection coll, bool lazyValidation)
- {
- if (coll == null)
- return;
- form = coll;
- lazyFormValidation = lazyValidation;
- }
- internal void SetQueryStringCollection (WebROCollection coll, bool lazyValidation)
- {
- if (coll == null)
- return;
- query_string_nvc = coll;
- lazyQueryStringValidation = lazyValidation;
- }
- #endif
- // Headers is ReadOnly, so we need this hack for cookie-less sessions.
- internal void SetHeader (string name, string value)
- {
- WebROCollection h = (WebROCollection) Headers;
- h.Unprotect ();
- h [name] = value;
- h.Protect ();
- }
- // Notice: there is nothing raw about this querystring.
- internal string QueryStringRaw {
- get {
- UriBuilder urlComponents = UrlComponents;
- if (urlComponents == null) {
- string ret = worker_request.GetQueryString ();
- if (ret == null || ret.Length == 0)
- return String.Empty;
- if (ret [0] == '?')
- return ret;
- return "?" + ret;
- }
-
- return UrlComponents.Query;
- }
- set {
- UrlComponents.Query = value;
- cached_url = null;
- query_string_nvc = null;
- }
- }
- // Internal, dont know what it does, so flagged as public so we can see it.
- internal void SetForm (WebROCollection coll)
- {
- form = coll;
- }
- internal HttpWorkerRequest WorkerRequest {
- get {
- return worker_request;
- }
- }
- internal HttpContext Context {
- get { return context; }
- set { context = value; }
- }
- static void ValidateNameValueCollection (string name, NameValueCollection coll)
- {
- if (coll == null)
- return;
-
- foreach (string key in coll.Keys) {
- string val = coll [key];
- if (val != null && val.Length > 0 && IsInvalidString (val))
- ThrowValidationException (name, key, val);
- }
- }
- #if NET_4_0
- static void ValidateNameValueCollection (string name, NameValueCollection coll, RequestValidationSource source)
- {
- if (coll == null)
- return;
- RequestValidator validator = RequestValidator.Current;
- int validationFailureIndex;
- HttpContext context = HttpContext.Current;
- foreach (string key in coll.Keys) {
- string val = coll [key];
- if (val != null && val.Length > 0 && !validator.IsValidRequestString (context, val, source, key, out validationFailureIndex))
- ThrowValidationException (name, key, val);
- }
- }
- [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
- public void InsertEntityBody ()
- {
- throw new PlatformNotSupportedException ("This method is not supported.");
- }
- [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
- public void InsertEntityBody (byte[] buffer, int offset, int count)
- {
- throw new PlatformNotSupportedException ("This method is not supported.");
- }
- #endif
- static void ValidateCookieCollection (HttpCookieCollection cookies)
- {
- if (cookies == null)
- return;
-
- int size = cookies.Count;
- HttpCookie cookie;
- #if NET_4_0
- RequestValidator validator = RequestValidator.Current;
- int validationFailureIndex;
- HttpContext context = HttpContext.Current;
- #endif
- bool invalid;
-
- for (int i = 0 ; i < size ; i++) {
- cookie = cookies[i];
- if (cookie == null)
- continue;
-
- string value = cookie.Value;
- string name = cookie.Name;
- if (!String.IsNullOrEmpty (value)) {
- #if NET_4_0
- if (validateRequestNewMode)
- invalid = !validator.IsValidRequestString (context, value, RequestValidationSource.Cookies, name, out validationFailureIndex);
- else
- #endif
- invalid = IsInvalidString (value);
- if (invalid)
- ThrowValidationException ("Cookies", name, value);
- }
- }
- }
- static void ThrowValidationException (string name, string key, string value)
- {
- 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);
-
- throw new HttpRequestValidationException (msg);
- }
- #if NET_4_0
- internal static void ValidateString (string key, string value, RequestValidationSource source)
- {
- if (String.IsNullOrEmpty (value))
- return;
- #pragma warning disable 219
- int ignore;
- #pragma warning restore 219
- if (IsInvalidString (value, out ignore))
- ThrowValidationException (source.ToString (), key, value);
- }
- #endif
- internal static bool IsInvalidString (string val)
- {
- #pragma warning disable 219
- int validationFailureIndex;
- #pragma warning restore 219
- return IsInvalidString (val, out validationFailureIndex);
- }
- internal static bool IsInvalidString (string val, out int validationFailureIndex)
- {
- validationFailureIndex = 0;
- int len = val.Length;
- if (len < 2)
- return false;
- char current = val [0];
- for (int idx = 1; idx < len; idx++) {
- char next = val [idx];
- // See http://secunia.com/advisories/14325
- if (current == '<' || current == '\xff1c') {
- if (next == '!' || next < ' '
- || (next >= 'a' && next <= 'z')
- || (next >= 'A' && next <= 'Z')) {
- validationFailureIndex = idx - 1;
- return true;
- }
- } else if (current == '&' && next == '#') {
- validationFailureIndex = idx - 1;
- return true;
- }
- current = next;
- }
- return false;
- }
-
- static System.Net.IPAddress [] GetLocalHostAddresses ()
- {
- try {
- string hostName = System.Net.Dns.GetHostName ();
- System.Net.IPAddress [] ipaddr = System.Net.Dns.GetHostAddresses (hostName);
- return ipaddr;
- } catch {
- return new System.Net.IPAddress[0];
- }
- }
- }
- #endregion
- #region Helper classes
- //
- // Stream-based multipart handling.
- //
- // In this incarnation deals with an HttpInputStream as we are now using
- // IntPtr-based streams instead of byte []. In the future, we will also
- // send uploads above a certain threshold into the disk (to implement
- // limit-less HttpInputFiles).
- //
-
- class HttpMultipart {
- public class Element {
- public string ContentType;
- public string Name;
- public string Filename;
- public long Start;
- public long Length;
-
- public override string ToString ()
- {
- return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " +
- Start.ToString () + ", Length " + Length.ToString ();
- }
- }
-
- Stream data;
- string boundary;
- byte [] boundary_bytes;
- byte [] buffer;
- bool at_eof;
- Encoding encoding;
- StringBuilder sb;
-
- const byte HYPHEN = (byte) '-', LF = (byte) '\n', CR = (byte) '\r';
-
- // See RFC 2046
- // In the case of multipart entities, in which one or more different
- // sets of data are combined in a single body, a "multipart" media type
- // field must appear in the entity's header. The body must then contain
- // one or more body parts, each preceded by a boundary delimiter line,
- // and the last one followed by a closing boundary delimiter line.
- // After its boundary delimiter line, each body part then consists of a
- // header area, a blank line, and a body area. Thus a body part is
- // similar to an RFC 822 message in syntax, but different in meaning.
-
- public HttpMultipart (Stream data, string b, Encoding encoding)
- {
- this.data = data;
- boundary = b;
- boundary_bytes = encoding.GetBytes (b);
- buffer = new byte [boundary_bytes.Length + 2]; // CRLF or '--'
- this.encoding = encoding;
- sb = new StringBuilder ();
- }
- string ReadLine ()
- {
- // CRLF or LF are ok as line endings.
- bool got_cr = false;
- int b = 0;
- sb.Length = 0;
- while (true) {
- b = data.ReadByte ();
- if (b == -1) {
- return null;
- }
- if (b == LF) {
- break;
- }
- got_cr = (b == CR);
- sb.Append ((char) b);
- }
- if (got_cr)
- sb.Length--;
- return sb.ToString ();
- }
- 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 l.Substring (begin, end - begin);
- }
- 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 "";
- 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);
- }
- bool ReadBoundary ()
- {
- try {
- string line = ReadLine ();
- while (line == "")
- line = ReadLine ();
- if (line [0] != '-' || line [1] != '-')
- return false;
- if (!StrUtils.EndsWith (line, boundary, false))
- return true;
- } catch {
- }
- return false;
- }
- string ReadHeaders ()
- {
- string s = ReadLine ();
- if (s == "")
- return null;
- return s;
- }
- 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 ()
- {
- long retval = 0;
- bool got_cr = false;
- int state = 0;
- int c = data.ReadByte ();
- 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 ();
- } else if (state == 0) {
- got_cr = (c == CR);
- c = data.ReadByte ();
- } else if (state == 1 && c == '-') {
- c = data.ReadByte ();
- if (c == -1)
- return -1;
- if (c != '-') {
- state = 0;
- got_cr = false;
- continue; // no ReadByte() here
- }
- int nread = data.Read (buffer, 0, buffer.Length);
- int bl = buffer.Length;
- if (nread != bl)
- return -1;
- if (!CompareBytes (boundary_bytes, buffer)) {
- state = 0;
- data.Position = retval + 2;
- if (got_cr) {
- data.Position++;
- got_cr = false;
- }
- c = data.ReadByte ();
- continue;
- }
- if (buffer [bl - 2] == '-' && buffer [bl - 1] == '-') {
- at_eof = true;
- } else if (buffer [bl - 2] != CR || buffer [bl - 1] != LF) {
- state = 0;
- data.Position = retval + 2;
- if (got_cr) {
- data.Position++;
- got_cr = false;
- }
- c = data.ReadByte ();
- continue;
- }
- data.Position = retval + 2;
- if (got_cr)
- data.Position++;
- break;
- } else {
- // state == 1
- state = 0; // no ReadByte() here
- }
- }
- return retval;
- }
- public Element ReadNextElement ()
- {
- if (at_eof || ReadBoundary ())
- return null;
- Element elem = new Element ();
- string header;
- while ((header = ReadHeaders ()) != null) {
- if (StrUtils.StartsWith (header, "Content-Disposition:", true)) {
- elem.Name = GetContentDispositionAttribute (header, "name");
- elem.Filename = StripPath (GetContentDispositionAttributeWithEncoding (header, "filename"));
- } else if (StrUtils.StartsWith (header, "Content-Type:", true)) {
- elem.ContentType = header.Substring ("Content-Type:".Length).Trim ();
- }
- }
- long start = data.Position;
- elem.Start = start;
- long pos = MoveToNextBoundary ();
- if (pos == -1)
- return null;
- elem.Length = pos - start;
- return elem;
- }
- static string StripPath (string path)
- {
- if (path == null || path.Length == 0)
- return path;
-
- if (path.IndexOf (":\\") != 1 && !path.StartsWith ("\\\\"))
- return path;
- return path.Substring (path.LastIndexOf ('\\') + 1);
- }
- }
- #endregion
- }
|