1 //------------------------------------------------------------------------------ 2 // <copyright file="httpserverutility.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 //------------------------------------------------------------------------------ 6 7 /* 8 * Server intrinsic used to match ASP's object model 9 * 10 * Copyright (c) 1999 Microsoft Corporation 11 */ 12 13 // Don't entity encode high chars (160 to 256), to fix bugs VSWhidbey 85857/111927 14 // 15 #define ENTITY_ENCODE_HIGH_ASCII_CHARS 16 17 namespace System.Web { 18 using System.Collections; 19 using System.Collections.Specialized; 20 using System.Globalization; 21 using System.IO; 22 using System.Security.Permissions; 23 using System.Text; 24 using System.Threading; 25 using System.Web.Configuration; 26 using System.Web.Hosting; 27 using System.Web.UI; 28 using System.Web.Util; 29 30 internal abstract class ErrorFormatterGenerator { GetErrorFormatter(Exception e)31 internal abstract ErrorFormatter GetErrorFormatter(Exception e); 32 } 33 34 35 /// <devdoc> 36 /// <para> 37 /// Provides several 38 /// helper methods that can be used in the processing of Web requests. 39 /// </para> 40 /// </devdoc> 41 public sealed class HttpServerUtility { 42 private HttpContext _context; 43 private HttpApplication _application; 44 45 private static IDictionary _cultureCache = Hashtable.Synchronized(new Hashtable()); 46 HttpServerUtility(HttpContext context)47 internal HttpServerUtility(HttpContext context) { 48 _context = context; 49 } 50 HttpServerUtility(HttpApplication application)51 internal HttpServerUtility(HttpApplication application) { 52 _application = application; 53 } 54 55 // 56 // Misc ASP compatibility methods 57 // 58 59 60 /// <devdoc> 61 /// <para> 62 /// Instantiates a COM object identified via a progid. 63 /// </para> 64 /// </devdoc> 65 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)] CreateObject(string progID)66 public object CreateObject(string progID) { 67 EnsureHasNotTransitionedToWebSocket(); 68 69 Type type = null; 70 object obj = null; 71 72 try { 73 #if !FEATURE_PAL // FEATURE_PAL does not enable COM 74 type = Type.GetTypeFromProgID(progID); 75 #else // !FEATURE_PAL 76 throw new NotImplementedException("ROTORTODO"); 77 #endif // !FEATURE_PAL 78 } 79 catch { 80 } 81 82 if (type == null) { 83 throw new HttpException(SR.GetString(SR.Could_not_create_object_of_type, progID)); 84 } 85 86 // Disallow Apartment components in non-compat mode 87 AspCompatApplicationStep.CheckThreadingModel(progID, type.GUID); 88 89 // Instantiate the object 90 obj = Activator.CreateInstance(type); 91 92 // For ASP compat: take care of OnPageStart/OnPageEnd 93 AspCompatApplicationStep.OnPageStart(obj); 94 95 return obj; 96 } 97 98 99 /// <devdoc> 100 /// <para> 101 /// Instantiates a COM object identified via a Type. 102 /// </para> 103 /// </devdoc> 104 [SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)] CreateObject(Type type)105 public object CreateObject(Type type) { 106 EnsureHasNotTransitionedToWebSocket(); 107 108 // Disallow Apartment components in non-compat mode 109 AspCompatApplicationStep.CheckThreadingModel(type.FullName, type.GUID); 110 111 // Instantiate the object 112 Object obj = Activator.CreateInstance(type); 113 114 // For ASP compat: take care of OnPageStart/OnPageEnd 115 AspCompatApplicationStep.OnPageStart(obj); 116 117 return obj; 118 } 119 120 121 122 /// <devdoc> 123 /// <para> 124 /// Instantiates a COM object identified via a clsid. 125 /// </para> 126 /// </devdoc> 127 [SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)] CreateObjectFromClsid(string clsid)128 public object CreateObjectFromClsid(string clsid) { 129 EnsureHasNotTransitionedToWebSocket(); 130 131 Type type = null; 132 object obj = null; 133 134 // Create a Guid out of it 135 Guid guid = new Guid(clsid); 136 137 // Disallow Apartment components in non-compat mode 138 AspCompatApplicationStep.CheckThreadingModel(clsid, guid); 139 140 try { 141 #if !FEATURE_PAL // FEATURE_PAL does not enable COM 142 type = Type.GetTypeFromCLSID(guid, null, true /*throwOnError*/); 143 #else // !FEATURE_PAL 144 throw new NotImplementedException("ROTORTODO"); 145 #endif // !FEATURE_PAL 146 147 // Instantiate the object 148 obj = Activator.CreateInstance(type); 149 } 150 catch { 151 } 152 153 if (obj == null) { 154 throw new HttpException( 155 SR.GetString(SR.Could_not_create_object_from_clsid, clsid)); 156 } 157 158 // For ASP compat: take care of OnPageStart/OnPageEnd 159 AspCompatApplicationStep.OnPageStart(obj); 160 161 return obj; 162 } 163 164 // Internal static method that returns a read-only, non-user override accounted, CultureInfo object CreateReadOnlyCultureInfo(string name)165 internal static CultureInfo CreateReadOnlyCultureInfo(string name) { 166 if (!_cultureCache.Contains(name)) { 167 // To be threadsafe, get the lock before creating 168 lock (_cultureCache) { 169 if (_cultureCache[name] == null) { 170 _cultureCache[name] = CultureInfo.ReadOnly(new CultureInfo(name)); 171 } 172 } 173 } 174 return (CultureInfo)_cultureCache[name]; 175 } 176 177 // Internal static method that returns a read-only, non-user override accounted, culture specific CultureInfo object CreateReadOnlySpecificCultureInfo(string name)178 internal static CultureInfo CreateReadOnlySpecificCultureInfo(string name) { 179 if(name.IndexOf('-') > 0) { 180 return CreateReadOnlyCultureInfo(name); 181 } 182 CultureInfo ci = CultureInfo.CreateSpecificCulture(name); 183 if (!_cultureCache.Contains(ci.Name)) { 184 //To be threadsafe, get the lock before creating 185 lock (_cultureCache) { 186 if (_cultureCache[ci.Name] == null) { 187 _cultureCache[ci.Name] = CultureInfo.ReadOnly(ci); 188 } 189 } 190 } 191 return (CultureInfo)_cultureCache[ci.Name]; 192 } 193 194 // Internal static method that returns a read-only, non-user override accounted, CultureInfo object CreateReadOnlyCultureInfo(int culture)195 internal static CultureInfo CreateReadOnlyCultureInfo(int culture) { 196 if (!_cultureCache.Contains(culture)) { 197 // To be threadsafe, get the lock before creating 198 lock (_cultureCache) { 199 if (_cultureCache[culture] == null) { 200 _cultureCache[culture] = CultureInfo.ReadOnly(new CultureInfo(culture)); 201 } 202 } 203 } 204 return (CultureInfo)_cultureCache[culture]; 205 } 206 207 /// <devdoc> 208 /// <para> 209 /// Maps a virtual path to a physical path. 210 /// </para> 211 /// </devdoc> MapPath(string path)212 public string MapPath(string path) { 213 if (_context == null) 214 throw new HttpException(SR.GetString(SR.Server_not_available)); 215 // Disable hiding the request so that Server.MapPath works when called from 216 // Application_Start in integrated mode 217 bool unhideRequest = _context.HideRequestResponse; 218 string realPath; 219 try { 220 if (unhideRequest) { 221 _context.HideRequestResponse = false; 222 } 223 realPath = _context.Request.MapPath(path); 224 } 225 finally { 226 if (unhideRequest) { 227 _context.HideRequestResponse = true; 228 } 229 } 230 return realPath; 231 } 232 233 234 /// <devdoc> 235 /// <para>Returns the last recorded exception.</para> 236 /// </devdoc> GetLastError()237 public Exception GetLastError() { 238 if (_context != null) 239 return _context.Error; 240 else if (_application != null) 241 return _application.LastError; 242 else 243 return null; 244 } 245 246 247 /// <devdoc> 248 /// <para>Clears the last error.</para> 249 /// </devdoc> ClearError()250 public void ClearError() { 251 if (_context != null) 252 _context.ClearError(); 253 else if (_application != null) 254 _application.ClearError(); 255 } 256 257 // 258 // Server.Transfer/Server.Execute -- child requests 259 // 260 261 262 /// <devdoc> 263 /// <para> 264 /// Executes a new request (using the specified URL path as the target). Unlike 265 /// the Transfer method, execution of the original page continues after the executed 266 /// page completes. 267 /// </para> 268 /// </devdoc> Execute(string path)269 public void Execute(string path) { 270 Execute(path, null, true /*preserveForm*/); 271 } 272 273 274 /// <devdoc> 275 /// <para> 276 /// Executes a new request (using the specified URL path as the target). Unlike 277 /// the Transfer method, execution of the original page continues after the executed 278 /// page completes. 279 /// </para> 280 /// </devdoc> Execute(string path, TextWriter writer)281 public void Execute(string path, TextWriter writer) { 282 Execute(path, writer, true /*preserveForm*/); 283 } 284 285 286 /// <devdoc> 287 /// <para> 288 /// Executes a new request (using the specified URL path as the target). Unlike 289 /// the Transfer method, execution of the original page continues after the executed 290 /// page completes. 291 /// If preserveForm is false, the QueryString and Form collections are cleared. 292 /// </para> 293 /// </devdoc> Execute(string path, bool preserveForm)294 public void Execute(string path, bool preserveForm) { 295 Execute(path, null, preserveForm); 296 } 297 298 299 /// <devdoc> 300 /// <para> 301 /// Executes a new request (using the specified URL path as the target). Unlike 302 /// the Transfer method, execution of the original page continues after the executed 303 /// page completes. 304 /// If preserveForm is false, the QueryString and Form collections are cleared. 305 /// </para> 306 /// </devdoc> Execute(string path, TextWriter writer, bool preserveForm)307 public void Execute(string path, TextWriter writer, bool preserveForm) { 308 EnsureHasNotTransitionedToWebSocket(); 309 310 if (_context == null) 311 throw new HttpException(SR.GetString(SR.Server_not_available)); 312 313 if (path == null) 314 throw new ArgumentNullException("path"); 315 316 string queryStringOverride = null; 317 HttpRequest request = _context.Request; 318 HttpResponse response = _context.Response; 319 320 // Remove potential cookie-less session id (ASURT 100558) 321 path = response.RemoveAppPathModifier(path); 322 323 // Allow query string override 324 int iqs = path.IndexOf('?'); 325 if (iqs >= 0) { 326 queryStringOverride = path.Substring(iqs+1); 327 path = path.Substring(0, iqs); 328 } 329 330 if (!UrlPath.IsValidVirtualPathWithoutProtocol(path)) { 331 throw new ArgumentException(SR.GetString(SR.Invalid_path_for_child_request, path)); 332 } 333 334 VirtualPath virtualPath = VirtualPath.Create(path); 335 336 // Find the handler for the path 337 338 IHttpHandler handler = null; 339 340 string physPath = request.MapPath(virtualPath); // get physical path 341 VirtualPath filePath = request.FilePathObject.Combine(virtualPath); // vpath 342 343 // Demand read access to the physical path of the target handler 344 InternalSecurityPermissions.FileReadAccess(physPath).Demand(); 345 346 // We need to Assert since there typically is user code on the stack (VSWhidbey 270965) 347 if (HttpRuntime.IsLegacyCas) { 348 InternalSecurityPermissions.Unrestricted.Assert(); 349 } 350 351 try { 352 // paths that ends with . are disallowed as they are used to get around 353 // extension mappings and server source as static file 354 if (StringUtil.StringEndsWith(virtualPath.VirtualPathString, '.')) 355 throw new HttpException(404, String.Empty); 356 357 bool useAppConfig = !filePath.IsWithinAppRoot; 358 359 using (new DisposableHttpContextWrapper(_context)) { 360 361 try { 362 // We need to increase the depth when calling MapHttpHandler, 363 // since PageHandlerFactory relies on it 364 _context.ServerExecuteDepth++; 365 366 if (_context.WorkerRequest is IIS7WorkerRequest) { 367 handler = _context.ApplicationInstance.MapIntegratedHttpHandler( 368 _context, 369 request.RequestType, 370 filePath, 371 physPath, 372 useAppConfig, 373 true /*convertNativeStaticFileModule*/); 374 } 375 else { 376 handler = _context.ApplicationInstance.MapHttpHandler( 377 _context, 378 request.RequestType, 379 filePath, 380 physPath, 381 useAppConfig); 382 } 383 } 384 finally { 385 _context.ServerExecuteDepth--; 386 } 387 } 388 } 389 catch (Exception e) { 390 // 500 errors (compilation errors) get preserved 391 if (e is HttpException) { 392 int code = ((HttpException)e).GetHttpCode(); 393 394 if (code != 500 && code != 404) { 395 e = null; 396 } 397 } 398 399 throw new HttpException(SR.GetString(SR.Error_executing_child_request_for_path, path), e); 400 } 401 402 ExecuteInternal(handler, writer, preserveForm, true /*setPreviousPage*/, 403 virtualPath, filePath, physPath, null, queryStringOverride); 404 } 405 406 Execute(IHttpHandler handler, TextWriter writer, bool preserveForm)407 public void Execute(IHttpHandler handler, TextWriter writer, bool preserveForm) { 408 if (_context == null) 409 throw new HttpException(SR.GetString(SR.Server_not_available)); 410 411 Execute(handler, writer, preserveForm, true /*setPreviousPage*/); 412 } 413 Execute(IHttpHandler handler, TextWriter writer, bool preserveForm, bool setPreviousPage)414 internal void Execute(IHttpHandler handler, TextWriter writer, bool preserveForm, bool setPreviousPage) { 415 HttpRequest request = _context.Request; 416 VirtualPath filePath = request.CurrentExecutionFilePathObject; 417 string physicalPath = request.MapPath(filePath); 418 419 ExecuteInternal(handler, writer, preserveForm, setPreviousPage, 420 null, filePath, physicalPath, null, null); 421 } 422 ExecuteInternal(IHttpHandler handler, TextWriter writer, bool preserveForm, bool setPreviousPage, VirtualPath path, VirtualPath filePath, string physPath, Exception error, string queryStringOverride)423 private void ExecuteInternal(IHttpHandler handler, TextWriter writer, bool preserveForm, bool setPreviousPage, 424 VirtualPath path, VirtualPath filePath, string physPath, Exception error, string queryStringOverride) { 425 426 EnsureHasNotTransitionedToWebSocket(); 427 428 if (handler == null) 429 throw new ArgumentNullException("handler"); 430 431 HttpRequest request = _context.Request; 432 HttpResponse response = _context.Response; 433 HttpApplication app = _context.ApplicationInstance; 434 435 HttpValueCollection savedForm = null; 436 VirtualPath savedCurrentExecutionFilePath = null; 437 string savedQueryString = null; 438 TextWriter savedOutputWriter = null; 439 AspNetSynchronizationContextBase savedSyncContext = null; 440 441 // Transaction wouldn't flow into ASPCOMPAT mode -- need to report an error 442 VerifyTransactionFlow(handler); 443 444 // create new trace context 445 _context.PushTraceContext(); 446 447 // set the new handler as the current handler 448 _context.SetCurrentHandler(handler); 449 450 // because we call this synchrnously async operations must be disabled 451 bool originalSyncContextWasEnabled = _context.SyncContext.Enabled; 452 _context.SyncContext.Disable(); 453 454 // Execute the handler 455 try { 456 try { 457 _context.ServerExecuteDepth++; 458 459 savedCurrentExecutionFilePath = request.SwitchCurrentExecutionFilePath(filePath); 460 461 if (!preserveForm) { 462 savedForm = request.SwitchForm(new HttpValueCollection()); 463 464 // Clear out the query string, but honor overrides 465 if (queryStringOverride == null) 466 queryStringOverride = String.Empty; 467 } 468 469 // override query string if requested 470 if (queryStringOverride != null) { 471 savedQueryString = request.QueryStringText; 472 request.QueryStringText = queryStringOverride; 473 } 474 475 // capture output if requested 476 if (writer != null) 477 savedOutputWriter = response.SwitchWriter(writer); 478 479 Page targetPage = handler as Page; 480 if (targetPage != null) { 481 if (setPreviousPage) { 482 // Set the previousPage of the new Page as the previous Page 483 targetPage.SetPreviousPage(_context.PreviousHandler as Page); 484 } 485 486 Page sourcePage = _context.Handler as Page; 487 488 #pragma warning disable 0618 // To avoid deprecation warning 489 // If the source page of the transfer has smart nav on, 490 // always do as if the destination has it too (ASURT 97732) 491 if (sourcePage != null && sourcePage.SmartNavigation) 492 targetPage.SmartNavigation = true; 493 #pragma warning restore 0618 494 495 // If the target page is async need to save/restore sync context 496 if (targetPage is IHttpAsyncHandler) { 497 savedSyncContext = _context.InstallNewAspNetSynchronizationContext(); 498 } 499 } 500 501 if ((handler is StaticFileHandler || handler is DefaultHttpHandler) && 502 !DefaultHttpHandler.IsClassicAspRequest(filePath.VirtualPathString)) { 503 // cannot apply static files handler directly 504 // -- it would dump the source of the current page 505 // instead just dump the file content into response 506 try { 507 response.WriteFile(physPath); 508 } 509 catch { 510 // hide the real error as it could be misleading 511 // in case of mismapped requests like /foo.asmx/bar 512 error = new HttpException(404, String.Empty); 513 } 514 } 515 else if (!(handler is Page)) { 516 // disallow anything but pages 517 error = new HttpException(404, String.Empty); 518 } 519 else if (handler is IHttpAsyncHandler) { 520 // Asynchronous handler 521 522 // suspend cancellable period (don't abort this thread while 523 // we wait for another to finish) 524 bool isCancellable = _context.IsInCancellablePeriod; 525 if (isCancellable) 526 _context.EndCancellablePeriod(); 527 528 try { 529 IHttpAsyncHandler asyncHandler = (IHttpAsyncHandler)handler; 530 531 if (!AppSettings.UseTaskFriendlySynchronizationContext) { 532 // Legacy code path: behavior ASP.NET <= 4.0 533 534 IAsyncResult ar = asyncHandler.BeginProcessRequest(_context, null, null); 535 536 // wait for completion 537 if (!ar.IsCompleted) { 538 // suspend app lock while waiting 539 bool needToRelock = false; 540 541 try { 542 try { } 543 finally { 544 _context.SyncContext.DisassociateFromCurrentThread(); 545 needToRelock = true; 546 } 547 548 WaitHandle h = ar.AsyncWaitHandle; 549 550 if (h != null) { 551 h.WaitOne(); 552 } 553 else { 554 while (!ar.IsCompleted) 555 Thread.Sleep(1); 556 } 557 } 558 finally { 559 if (needToRelock) { 560 _context.SyncContext.AssociateWithCurrentThread(); 561 } 562 } 563 } 564 565 // end the async operation (get error if any) 566 567 try { 568 asyncHandler.EndProcessRequest(ar); 569 } 570 catch (Exception e) { 571 error = e; 572 } 573 } 574 else { 575 // New code path: behavior ASP.NET >= 4.5 576 IAsyncResult ar; 577 bool blockedThread; 578 579 using (CountdownEvent countdownEvent = new CountdownEvent(1)) { 580 using (_context.SyncContext.AcquireThreadLock()) { 581 // Kick off the asynchronous operation 582 ar = asyncHandler.BeginProcessRequest(_context, 583 cb: _ => { countdownEvent.Signal(); }, 584 extraData: null); 585 } 586 587 // The callback passed to BeginProcessRequest will signal the CountdownEvent. 588 // The Wait() method blocks until the callback executes; no-ops if the operation completed synchronously. 589 blockedThread = !countdownEvent.IsSet; 590 countdownEvent.Wait(); 591 } 592 593 // end the async operation (get error if any) 594 595 try { 596 using (_context.SyncContext.AcquireThreadLock()) { 597 asyncHandler.EndProcessRequest(ar); 598 } 599 600 // If we blocked the thread, YSOD the request to display a diagnostic message. 601 if (blockedThread && !_context.SyncContext.AllowAsyncDuringSyncStages) { 602 throw new InvalidOperationException(SR.GetString(SR.Server_execute_blocked_on_async_handler)); 603 } 604 } 605 catch (Exception e) { 606 error = e; 607 } 608 } 609 } 610 finally { 611 // resume cancelleable period 612 if (isCancellable) 613 _context.BeginCancellablePeriod(); 614 } 615 } 616 else { 617 // Synchronous handler 618 619 using (new DisposableHttpContextWrapper(_context)) { 620 try { 621 handler.ProcessRequest(_context); 622 } 623 catch (Exception e) { 624 error = e; 625 } 626 } 627 } 628 } 629 finally { 630 _context.ServerExecuteDepth--; 631 632 // Restore the handlers; 633 _context.RestoreCurrentHandler(); 634 635 // restore output writer 636 if (savedOutputWriter != null) 637 response.SwitchWriter(savedOutputWriter); 638 639 // restore overriden query string 640 if (queryStringOverride != null && savedQueryString != null) 641 request.QueryStringText = savedQueryString; 642 643 if (savedForm != null) 644 request.SwitchForm(savedForm); 645 646 request.SwitchCurrentExecutionFilePath(savedCurrentExecutionFilePath); 647 648 if (savedSyncContext != null) { 649 _context.RestoreSavedAspNetSynchronizationContext(savedSyncContext); 650 } 651 652 if (originalSyncContextWasEnabled) { 653 _context.SyncContext.Enable(); 654 } 655 656 // restore trace context 657 _context.PopTraceContext(); 658 } 659 } 660 catch { // Protect against exception filters 661 throw; 662 } 663 664 // Report any error 665 if (error != null) { 666 // suppress errors with HTTP codes (for child requests they mislead more than help) 667 if (error is HttpException && ((HttpException)error).GetHttpCode() != 500) 668 error = null; 669 670 if (path != null) 671 throw new HttpException(SR.GetString(SR.Error_executing_child_request_for_path, path), error); 672 673 throw new HttpException(SR.GetString(SR.Error_executing_child_request_for_handler, handler.GetType().ToString()), error); 674 } 675 } 676 677 678 /// <devdoc> 679 /// <para> 680 /// Terminates execution of the current page and begins execution of a new 681 /// request using the supplied URL path. 682 /// If preserveForm is false, the QueryString and Form collections are cleared. 683 /// </para> 684 /// </devdoc> Transfer(string path, bool preserveForm)685 public void Transfer(string path, bool preserveForm) { 686 Page page = _context.Handler as Page; 687 if ((page != null) && page.IsCallback) { 688 throw new ApplicationException(SR.GetString(SR.Transfer_not_allowed_in_callback)); 689 } 690 691 // execute child request 692 693 Execute(path, null, preserveForm); 694 695 // suppress the remainder of the current one 696 697 _context.Response.End(); 698 } 699 700 701 /// <devdoc> 702 /// <para> 703 /// Terminates execution of the current page and begins execution of a new 704 /// request using the supplied URL path. 705 /// </para> 706 /// </devdoc> Transfer(string path)707 public void Transfer(string path) { 708 // Make sure the transfer is not treated as a postback, which could cause a stack 709 // overflow if the user doesn't expect it (VSWhidbey 181013). 710 // If the use *does* want it treated as a postback, they can call Transfer(path, true). 711 bool savedPreventPostback = _context.PreventPostback; 712 _context.PreventPostback = true; 713 714 Transfer(path, true /*preserveForm*/); 715 716 _context.PreventPostback = savedPreventPostback; 717 } 718 719 Transfer(IHttpHandler handler, bool preserveForm)720 public void Transfer(IHttpHandler handler, bool preserveForm) { 721 Page page = handler as Page; 722 if ((page != null) && page.IsCallback) { 723 throw new ApplicationException(SR.GetString(SR.Transfer_not_allowed_in_callback)); 724 } 725 726 Execute(handler, null, preserveForm); 727 728 // suppress the remainder of the current one 729 730 _context.Response.End(); 731 } 732 TransferRequest(string path)733 public void TransferRequest(string path) 734 { 735 TransferRequest(path, false, null, null, preserveUser: true); 736 } 737 TransferRequest(string path, bool preserveForm)738 public void TransferRequest(string path, bool preserveForm) 739 { 740 TransferRequest(path, preserveForm, null, null, preserveUser: true); 741 } 742 TransferRequest(string path, bool preserveForm, string method, NameValueCollection headers)743 public void TransferRequest(string path, bool preserveForm, string method, NameValueCollection headers) { 744 TransferRequest(path, preserveForm, method, headers, preserveUser: true); 745 } 746 TransferRequest(string path, bool preserveForm, string method, NameValueCollection headers, bool preserveUser)747 public void TransferRequest(string path, bool preserveForm, string method, NameValueCollection headers, bool preserveUser) { 748 EnsureHasNotTransitionedToWebSocket(); 749 750 if (!HttpRuntime.UseIntegratedPipeline) { 751 throw new PlatformNotSupportedException(SR.GetString(SR.Requires_Iis_Integrated_Mode)); 752 } 753 754 if (_context == null) { 755 throw new HttpException(SR.GetString(SR.Server_not_available)); 756 } 757 758 if (path == null) { 759 throw new ArgumentNullException("path"); 760 } 761 762 IIS7WorkerRequest wr = _context.WorkerRequest as IIS7WorkerRequest; 763 HttpRequest request = _context.Request; 764 HttpResponse response = _context.Response; 765 766 if (wr == null) { 767 throw new HttpException(SR.GetString(SR.Server_not_available)); 768 } 769 770 // Remove potential cookie-less session id (ASURT 100558) 771 path = response.RemoveAppPathModifier(path); 772 773 // Extract query string if specified 774 String qs = null; 775 int iqs = path.IndexOf('?'); 776 if (iqs >= 0) { 777 qs = (iqs < path.Length-1) ? path.Substring(iqs+1) : String.Empty; 778 path = path.Substring(0, iqs); 779 } 780 781 if (!UrlPath.IsValidVirtualPathWithoutProtocol(path)) { 782 throw new ArgumentException(SR.GetString(SR.Invalid_path_for_child_request, path)); 783 } 784 785 VirtualPath virtualPath = request.FilePathObject.Combine(VirtualPath.Create(path)); 786 787 // Schedule the child execution 788 wr.ScheduleExecuteUrl( virtualPath.VirtualPathString, 789 qs, 790 method, 791 preserveForm, 792 preserveForm ? request.EntityBody : null, 793 headers, 794 preserveUser); 795 796 // force the completion of the current request so that the 797 // child execution can be performed immediately after unwind 798 _context.ApplicationInstance.EnsureReleaseState(); 799 800 // DevDiv Bugs 162750: IIS7 Integrated Mode: TransferRequest performance issue 801 // Instead of calling Response.End we call HttpApplication.CompleteRequest() 802 _context.ApplicationInstance.CompleteRequest(); 803 } 804 VerifyTransactionFlow(IHttpHandler handler)805 private void VerifyTransactionFlow(IHttpHandler handler) { 806 Page topPage = _context.Handler as Page; 807 Page childPage = handler as Page; 808 809 if (childPage != null && childPage.IsInAspCompatMode && // child page aspcompat 810 topPage != null && !topPage.IsInAspCompatMode && // top page is not aspcompat 811 Transactions.Utils.IsInTransaction) { // we are in transaction 812 813 throw new HttpException(SR.GetString(SR.Transacted_page_calls_aspcompat)); 814 } 815 } 816 817 // 818 // Static method to execute a request outside of HttpContext and capture the response 819 // 820 ExecuteLocalRequestAndCaptureResponse(String path, TextWriter writer, ErrorFormatterGenerator errorFormatterGenerator)821 internal static void ExecuteLocalRequestAndCaptureResponse(String path, TextWriter writer, 822 ErrorFormatterGenerator errorFormatterGenerator) { 823 HttpRequest request = new HttpRequest( 824 VirtualPath.CreateAbsolute(path), 825 String.Empty); 826 827 HttpResponse response = new HttpResponse(writer); 828 829 HttpContext context = new HttpContext(request, response); 830 831 HttpApplication app = HttpApplicationFactory.GetApplicationInstance(context) as HttpApplication; 832 context.ApplicationInstance = app; 833 834 try { 835 context.Server.Execute(path); 836 } 837 catch (HttpException e) { 838 if (errorFormatterGenerator != null) { 839 context.Response.SetOverrideErrorFormatter(errorFormatterGenerator.GetErrorFormatter(e)); 840 } 841 842 context.Response.ReportRuntimeError(e, false, true); 843 } 844 finally { 845 if (app != null) { 846 context.ApplicationInstance = null; 847 HttpApplicationFactory.RecycleApplicationInstance(app); 848 } 849 } 850 } 851 852 // 853 // Computer name 854 // 855 856 private static object _machineNameLock = new object(); 857 private static string _machineName; 858 private const int _maxMachineNameLength = 256; 859 860 861 /// <devdoc> 862 /// <para> 863 /// Gets 864 /// the server machine name. 865 /// </para> 866 /// </devdoc> 867 public string MachineName { 868 [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] 869 get { 870 return GetMachineNameInternal(); 871 } 872 } 873 GetMachineNameInternal()874 internal static string GetMachineNameInternal() 875 { 876 if (_machineName != null) 877 return _machineName; 878 lock (_machineNameLock) 879 { 880 if (_machineName != null) 881 return _machineName; 882 883 StringBuilder buf = new StringBuilder (_maxMachineNameLength); 884 int len = _maxMachineNameLength; 885 886 if (UnsafeNativeMethods.GetComputerName (buf, ref len) == 0) 887 throw new HttpException (SR.GetString(SR.Get_computer_name_failed)); 888 889 _machineName = buf.ToString(); 890 } 891 return _machineName; 892 } 893 894 // 895 // Request Timeout 896 // 897 898 899 /// <devdoc> 900 /// <para> 901 /// Request timeout in seconds 902 /// </para> 903 /// </devdoc> 904 public int ScriptTimeout { 905 get { 906 if (_context != null) { 907 return Convert.ToInt32(_context.Timeout.TotalSeconds); 908 } 909 else { 910 return HttpRuntimeSection.DefaultExecutionTimeout; 911 } 912 } 913 914 [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] 915 set { 916 if (_context == null) 917 throw new HttpException(SR.GetString(SR.Server_not_available)); 918 if (value <= 0) 919 throw new ArgumentOutOfRangeException("value"); 920 _context.Timeout = new TimeSpan(0, 0, value); 921 } 922 } 923 924 // 925 // Encoding / Decoding -- wrappers for HttpUtility 926 // 927 928 929 /// <devdoc> 930 /// <para> 931 /// HTML 932 /// decodes a given string and 933 /// returns the decoded string. 934 /// </para> 935 /// </devdoc> HtmlDecode(string s)936 public string HtmlDecode(string s) { 937 return HttpUtility.HtmlDecode(s); 938 } 939 940 941 /// <devdoc> 942 /// <para> 943 /// HTML 944 /// decode a string and send the result to a TextWriter output 945 /// stream. 946 /// </para> 947 /// </devdoc> HtmlDecode(string s, TextWriter output)948 public void HtmlDecode(string s, TextWriter output) { 949 HttpUtility.HtmlDecode(s, output); 950 } 951 952 953 /// <devdoc> 954 /// <para> 955 /// HTML 956 /// encodes a given string and 957 /// returns the encoded string. 958 /// </para> 959 /// </devdoc> HtmlEncode(string s)960 public string HtmlEncode(string s) { 961 return HttpUtility.HtmlEncode(s); 962 } 963 964 965 /// <devdoc> 966 /// <para> 967 /// HTML 968 /// encodes 969 /// a string and returns the output to a TextWriter stream of output. 970 /// </para> 971 /// </devdoc> HtmlEncode(string s, TextWriter output)972 public void HtmlEncode(string s, TextWriter output) { 973 HttpUtility.HtmlEncode(s, output); 974 } 975 976 977 /// <devdoc> 978 /// <para> 979 /// URL 980 /// encodes a given 981 /// string and returns the encoded string. 982 /// </para> 983 /// </devdoc> UrlEncode(string s)984 public string UrlEncode(string s) { 985 Encoding e = (_context != null) ? _context.Response.ContentEncoding : Encoding.UTF8; 986 return HttpUtility.UrlEncode(s, e); 987 } 988 989 990 /// <devdoc> 991 /// <para> 992 /// URL encodes a path portion of a URL string and returns the encoded string. 993 /// </para> 994 /// </devdoc> UrlPathEncode(string s)995 public string UrlPathEncode(string s) { 996 return HttpUtility.UrlPathEncode(s); 997 } 998 999 1000 /// <devdoc> 1001 /// <para> 1002 /// URL 1003 /// encodes 1004 /// a string and returns the output to a TextWriter output stream. 1005 /// </para> 1006 /// </devdoc> UrlEncode(string s, TextWriter output)1007 public void UrlEncode(string s, TextWriter output) { 1008 if (s != null) 1009 output.Write(UrlEncode(s)); 1010 } 1011 1012 1013 /// <devdoc> 1014 /// <para> 1015 /// URL decodes a string and returns the output in a string. 1016 /// </para> 1017 /// </devdoc> UrlDecode(string s)1018 public string UrlDecode(string s) { 1019 Encoding e = (_context != null) ? _context.Request.ContentEncoding : Encoding.UTF8; 1020 return HttpUtility.UrlDecode(s, e); 1021 } 1022 1023 1024 /// <devdoc> 1025 /// <para> 1026 /// URL decodes a string and returns the output as a TextWriter output 1027 /// stream. 1028 /// </para> 1029 /// </devdoc> UrlDecode(string s, TextWriter output)1030 public void UrlDecode(string s, TextWriter output) { 1031 if (s != null) 1032 output.Write(UrlDecode(s)); 1033 } 1034 1035 ///////////////////////////////////////////////////////////////////////////// 1036 ///////////////////////////////////////////////////////////////////////////// 1037 ///////////////////////////////////////////////////////////////////////////// 1038 UrlTokenEncode(byte [] input)1039 static public string UrlTokenEncode(byte [] input) 1040 { 1041 return HttpEncoder.Current.UrlTokenEncode(input); 1042 } 1043 1044 ///////////////////////////////////////////////////////////////////////////// 1045 ///////////////////////////////////////////////////////////////////////////// 1046 ///////////////////////////////////////////////////////////////////////////// 1047 UrlTokenDecode(string input)1048 static public byte [] UrlTokenDecode(string input) { 1049 return HttpEncoder.Current.UrlTokenDecode(input); 1050 } 1051 1052 // helper that throws an exception if we have transitioned the current request to a WebSocket request EnsureHasNotTransitionedToWebSocket()1053 internal void EnsureHasNotTransitionedToWebSocket() { 1054 if (_context != null) { 1055 _context.EnsureHasNotTransitionedToWebSocket(); 1056 } 1057 } 1058 } 1059 1060 1061 /// <devdoc> 1062 /// </devdoc> 1063 1064 // VSWhidbey 473228 - removed link demand from HttpUtility for ClickOnce scenario 1065 public sealed class HttpUtility { 1066 HttpUtility()1067 public HttpUtility () {} 1068 1069 ////////////////////////////////////////////////////////////////////////// 1070 // 1071 // HTML Encoding / Decoding 1072 // 1073 1074 1075 /// <devdoc> 1076 /// <para> 1077 /// HTML decodes a string and returns the decoded string. 1078 /// </para> 1079 /// </devdoc> HtmlDecode(string s)1080 public static string HtmlDecode(string s) { 1081 return HttpEncoder.Current.HtmlDecode(s); 1082 } 1083 1084 1085 /// <devdoc> 1086 /// <para> 1087 /// HTML decode a string and send the result to a TextWriter output stream. 1088 /// </para> 1089 /// </devdoc> HtmlDecode(string s, TextWriter output)1090 public static void HtmlDecode(string s, TextWriter output) { 1091 HttpEncoder.Current.HtmlDecode(s, output); 1092 } 1093 1094 1095 /// <devdoc> 1096 /// <para> 1097 /// HTML encodes a string and returns the encoded string. 1098 /// </para> 1099 /// </devdoc> HtmlEncode(String s)1100 public static String HtmlEncode(String s) { 1101 return HttpEncoder.Current.HtmlEncode(s); 1102 } 1103 1104 1105 /// <devdoc> 1106 /// <para> 1107 /// HTML encodes an object's string representation and returns the encoded string. 1108 /// If the object implements IHtmlString, don't encode it 1109 /// </para> 1110 /// </devdoc> HtmlEncode(object value)1111 public static String HtmlEncode(object value) { 1112 if (value == null) { 1113 // Return null to be consistent with HtmlEncode(string) 1114 return null; 1115 } 1116 1117 var htmlString = value as IHtmlString; 1118 if (htmlString != null) { 1119 return htmlString.ToHtmlString(); 1120 } 1121 1122 return HtmlEncode(Convert.ToString(value, CultureInfo.CurrentCulture)); 1123 } 1124 1125 1126 /// <devdoc> 1127 /// <para> 1128 /// HTML encodes a string and returns the output to a TextWriter stream of 1129 /// output. 1130 /// </para> 1131 /// </devdoc> HtmlEncode(String s, TextWriter output)1132 public static void HtmlEncode(String s, TextWriter output) { 1133 HttpEncoder.Current.HtmlEncode(s, output); 1134 } 1135 1136 1137 /// <devdoc> 1138 /// <para> 1139 /// Encodes a string to make it a valid HTML attribute and returns the encoded string. 1140 /// </para> 1141 /// </devdoc> HtmlAttributeEncode(String s)1142 public static String HtmlAttributeEncode(String s) { 1143 return HttpEncoder.Current.HtmlAttributeEncode(s); 1144 } 1145 1146 1147 /// <devdoc> 1148 /// <para> 1149 /// Encodes a string to make it a valid HTML attribute and returns the output 1150 /// to a TextWriter stream of 1151 /// output. 1152 /// </para> 1153 /// </devdoc> HtmlAttributeEncode(String s, TextWriter output)1154 public static void HtmlAttributeEncode(String s, TextWriter output) { 1155 HttpEncoder.Current.HtmlAttributeEncode(s, output); 1156 } 1157 1158 FormatPlainTextSpacesAsHtml(string s)1159 internal static string FormatPlainTextSpacesAsHtml(string s) { 1160 if (s == null) { 1161 return null; 1162 } 1163 1164 StringBuilder builder = new StringBuilder(); 1165 StringWriter writer = new StringWriter(builder); 1166 1167 int cb = s.Length; 1168 1169 for (int i = 0; i < cb; i++) { 1170 char ch = s[i]; 1171 if(ch == ' ') { 1172 writer.Write(" "); 1173 } 1174 else { 1175 writer.Write(ch); 1176 } 1177 } 1178 return builder.ToString(); 1179 } 1180 FormatPlainTextAsHtml(String s)1181 internal static String FormatPlainTextAsHtml(String s) { 1182 if (s == null) 1183 return null; 1184 1185 StringBuilder builder = new StringBuilder(); 1186 StringWriter writer = new StringWriter(builder); 1187 1188 FormatPlainTextAsHtml(s, writer); 1189 1190 return builder.ToString(); 1191 } 1192 FormatPlainTextAsHtml(String s, TextWriter output)1193 internal static void FormatPlainTextAsHtml(String s, TextWriter output) { 1194 if (s == null) 1195 return; 1196 1197 int cb = s.Length; 1198 1199 char prevCh = '\0'; 1200 1201 for (int i=0; i<cb; i++) { 1202 char ch = s[i]; 1203 switch (ch) { 1204 case '<': 1205 output.Write("<"); 1206 break; 1207 case '>': 1208 output.Write(">"); 1209 break; 1210 case '"': 1211 output.Write("""); 1212 break; 1213 case '&': 1214 output.Write("&"); 1215 break; 1216 case ' ': 1217 if (prevCh == ' ') 1218 output.Write(" "); 1219 else 1220 output.Write(ch); 1221 break; 1222 case '\r': 1223 // Ignore \r, only handle \n 1224 break; 1225 case '\n': 1226 output.Write("<br>"); 1227 break; 1228 1229 // 1230 default: 1231 #if ENTITY_ENCODE_HIGH_ASCII_CHARS 1232 // The seemingly arbitrary 160 comes from RFC 1233 if (ch >= 160 && ch < 256) { 1234 output.Write("&#"); 1235 output.Write(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); 1236 output.Write(';'); 1237 break; 1238 } 1239 #endif // ENTITY_ENCODE_HIGH_ASCII_CHARS 1240 1241 output.Write(ch); 1242 break; 1243 } 1244 1245 prevCh = ch; 1246 } 1247 } 1248 1249 1250 ////////////////////////////////////////////////////////////////////////// 1251 // 1252 // ASII encode - everything all non-7-bit to '?' 1253 // 1254 1255 /*internal static String AsciiEncode(String s) { 1256 if (s == null) 1257 return null; 1258 1259 StringBuilder sb = new StringBuilder(s.Length); 1260 1261 for (int i = 0; i < s.Length; i++) { 1262 char ch = s[i]; 1263 if (((ch & 0xff80) != 0) || (ch < ' ' && ch != '\r' && ch != '\n' && ch != '\t')) 1264 ch = '?'; 1265 sb.Append(ch); 1266 } 1267 1268 return sb.ToString(); 1269 }*/ 1270 1271 1272 // 1273 // Query string parsing support 1274 // 1275 ParseQueryString(string query)1276 public static NameValueCollection ParseQueryString(string query) { 1277 return ParseQueryString(query, Encoding.UTF8); 1278 } 1279 ParseQueryString(string query, Encoding encoding)1280 public static NameValueCollection ParseQueryString(string query, Encoding encoding) { 1281 if (query == null) { 1282 throw new ArgumentNullException("query"); 1283 } 1284 1285 if (encoding == null) { 1286 throw new ArgumentNullException("encoding"); 1287 } 1288 1289 if (query.Length > 0 && query[0] == '?') { 1290 query = query.Substring(1); 1291 } 1292 1293 return new HttpValueCollection(query, false, true, encoding); 1294 } 1295 1296 ////////////////////////////////////////////////////////////////////////// 1297 // 1298 // URL decoding / encoding 1299 // 1300 ////////////////////////////////////////////////////////////////////////// 1301 1302 // 1303 // Public static methods 1304 // 1305 1306 1307 /// <devdoc> 1308 /// <para>[To be supplied.]</para> 1309 /// </devdoc> UrlEncode(string str)1310 public static string UrlEncode(string str) { 1311 if (str == null) 1312 return null; 1313 return UrlEncode(str, Encoding.UTF8); 1314 } 1315 1316 1317 /// <devdoc> 1318 /// <para> 1319 /// URL encodes a path portion of a URL string and returns the encoded string. 1320 /// </para> 1321 /// </devdoc> UrlPathEncode(string str)1322 public static string UrlPathEncode(string str) { 1323 return HttpEncoder.Current.UrlPathEncode(str); 1324 } 1325 AspCompatUrlEncode(string s)1326 internal static string AspCompatUrlEncode(string s) { 1327 s = UrlEncode(s); 1328 s = s.Replace("!", "%21"); 1329 s = s.Replace("*", "%2A"); 1330 s = s.Replace("(", "%28"); 1331 s = s.Replace(")", "%29"); 1332 s = s.Replace("-", "%2D"); 1333 s = s.Replace(".", "%2E"); 1334 s = s.Replace("_", "%5F"); 1335 s = s.Replace("\\", "%5C"); 1336 return s; 1337 } 1338 1339 1340 /// <devdoc> 1341 /// <para>[To be supplied.]</para> 1342 /// </devdoc> UrlEncode(string str, Encoding e)1343 public static string UrlEncode(string str, Encoding e) { 1344 if (str == null) 1345 return null; 1346 return Encoding.ASCII.GetString(UrlEncodeToBytes(str, e)); 1347 } 1348 1349 // Helper to encode the non-ASCII url characters only UrlEncodeNonAscii(string str, Encoding e)1350 internal static String UrlEncodeNonAscii(string str, Encoding e) { 1351 return HttpEncoder.Current.UrlEncodeNonAscii(str, e); 1352 } 1353 1354 /// <devdoc> 1355 /// <para>[To be supplied.]</para> 1356 /// </devdoc> UrlEncode(byte[] bytes)1357 public static string UrlEncode(byte[] bytes) { 1358 if (bytes == null) 1359 return null; 1360 return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes)); 1361 } 1362 1363 1364 /// <devdoc> 1365 /// <para>[To be supplied.]</para> 1366 /// </devdoc> UrlEncode(byte[] bytes, int offset, int count)1367 public static string UrlEncode(byte[] bytes, int offset, int count) { 1368 if (bytes == null) 1369 return null; 1370 return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes, offset, count)); 1371 } 1372 1373 1374 /// <devdoc> 1375 /// <para>[To be supplied.]</para> 1376 /// </devdoc> UrlEncodeToBytes(string str)1377 public static byte[] UrlEncodeToBytes(string str) { 1378 if (str == null) 1379 return null; 1380 return UrlEncodeToBytes(str, Encoding.UTF8); 1381 } 1382 1383 1384 /// <devdoc> 1385 /// <para>[To be supplied.]</para> 1386 /// </devdoc> UrlEncodeToBytes(string str, Encoding e)1387 public static byte[] UrlEncodeToBytes(string str, Encoding e) { 1388 if (str == null) 1389 return null; 1390 byte[] bytes = e.GetBytes(str); 1391 return HttpEncoder.Current.UrlEncode(bytes, 0, bytes.Length, false /* alwaysCreateNewReturnValue */); 1392 } 1393 1394 1395 /// <devdoc> 1396 /// <para>[To be supplied.]</para> 1397 /// </devdoc> UrlEncodeToBytes(byte[] bytes)1398 public static byte[] UrlEncodeToBytes(byte[] bytes) { 1399 if (bytes == null) 1400 return null; 1401 return UrlEncodeToBytes(bytes, 0, bytes.Length); 1402 } 1403 1404 1405 /// <devdoc> 1406 /// <para>[To be supplied.]</para> 1407 /// </devdoc> UrlEncodeToBytes(byte[] bytes, int offset, int count)1408 public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) { 1409 return HttpEncoder.Current.UrlEncode(bytes, offset, count, true /* alwaysCreateNewReturnValue */); 1410 } 1411 1412 1413 /// <devdoc> 1414 /// <para>[To be supplied.]</para> 1415 /// </devdoc> 1416 [Obsolete("This method produces non-standards-compliant output and has interoperability issues. The preferred alternative is UrlEncode(String).")] UrlEncodeUnicode(string str)1417 public static string UrlEncodeUnicode(string str) { 1418 return HttpEncoder.Current.UrlEncodeUnicode(str, false /* ignoreAscii */); 1419 } 1420 1421 1422 /// <devdoc> 1423 /// <para>[To be supplied.]</para> 1424 /// </devdoc> 1425 [Obsolete("This method produces non-standards-compliant output and has interoperability issues. The preferred alternative is UrlEncodeToBytes(String).")] UrlEncodeUnicodeToBytes(string str)1426 public static byte[] UrlEncodeUnicodeToBytes(string str) { 1427 if (str == null) 1428 return null; 1429 return Encoding.ASCII.GetBytes(UrlEncodeUnicode(str)); 1430 } 1431 1432 1433 /// <devdoc> 1434 /// <para>[To be supplied.]</para> 1435 /// </devdoc> UrlDecode(string str)1436 public static string UrlDecode(string str) { 1437 if (str == null) 1438 return null; 1439 return UrlDecode(str, Encoding.UTF8); 1440 } 1441 1442 1443 /// <devdoc> 1444 /// <para>[To be supplied.]</para> 1445 /// </devdoc> UrlDecode(string str, Encoding e)1446 public static string UrlDecode(string str, Encoding e) { 1447 return HttpEncoder.Current.UrlDecode(str, e); 1448 } 1449 1450 1451 /// <devdoc> 1452 /// <para>[To be supplied.]</para> 1453 /// </devdoc> UrlDecode(byte[] bytes, Encoding e)1454 public static string UrlDecode(byte[] bytes, Encoding e) { 1455 if (bytes == null) 1456 return null; 1457 return UrlDecode(bytes, 0, bytes.Length, e); 1458 } 1459 1460 1461 /// <devdoc> 1462 /// <para>[To be supplied.]</para> 1463 /// </devdoc> UrlDecode(byte[] bytes, int offset, int count, Encoding e)1464 public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e) { 1465 return HttpEncoder.Current.UrlDecode(bytes, offset, count, e); 1466 } 1467 1468 1469 /// <devdoc> 1470 /// <para>[To be supplied.]</para> 1471 /// </devdoc> UrlDecodeToBytes(string str)1472 public static byte[] UrlDecodeToBytes(string str) { 1473 if (str == null) 1474 return null; 1475 return UrlDecodeToBytes(str, Encoding.UTF8); 1476 } 1477 1478 1479 /// <devdoc> 1480 /// <para>[To be supplied.]</para> 1481 /// </devdoc> UrlDecodeToBytes(string str, Encoding e)1482 public static byte[] UrlDecodeToBytes(string str, Encoding e) { 1483 if (str == null) 1484 return null; 1485 return UrlDecodeToBytes(e.GetBytes(str)); 1486 } 1487 1488 1489 /// <devdoc> 1490 /// <para>[To be supplied.]</para> 1491 /// </devdoc> UrlDecodeToBytes(byte[] bytes)1492 public static byte[] UrlDecodeToBytes(byte[] bytes) { 1493 if (bytes == null) 1494 return null; 1495 return UrlDecodeToBytes(bytes, 0, (bytes != null) ? bytes.Length : 0); 1496 } 1497 1498 1499 /// <devdoc> 1500 /// <para>[To be supplied.]</para> 1501 /// </devdoc> UrlDecodeToBytes(byte[] bytes, int offset, int count)1502 public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count) { 1503 return HttpEncoder.Current.UrlDecode(bytes, offset, count); 1504 } 1505 1506 1507 ////////////////////////////////////////////////////////////////////////// 1508 // 1509 // Misc helpers 1510 // 1511 ////////////////////////////////////////////////////////////////////////// 1512 FormatHttpDateTime(DateTime dt)1513 internal static String FormatHttpDateTime(DateTime dt) { 1514 if (dt < DateTime.MaxValue.AddDays(-1) && dt > DateTime.MinValue.AddDays(1)) 1515 dt = dt.ToUniversalTime(); 1516 return dt.ToString("R", DateTimeFormatInfo.InvariantInfo); 1517 } 1518 FormatHttpDateTimeUtc(DateTime dt)1519 internal static String FormatHttpDateTimeUtc(DateTime dt) { 1520 return dt.ToString("R", DateTimeFormatInfo.InvariantInfo); 1521 } 1522 FormatHttpCookieDateTime(DateTime dt)1523 internal static String FormatHttpCookieDateTime(DateTime dt) { 1524 if (dt < DateTime.MaxValue.AddDays(-1) && dt > DateTime.MinValue.AddDays(1)) 1525 dt = dt.ToUniversalTime(); 1526 return dt.ToString("ddd, dd-MMM-yyyy HH':'mm':'ss 'GMT'", DateTimeFormatInfo.InvariantInfo); 1527 } 1528 1529 // 1530 // JavaScriptStringEncode 1531 // 1532 JavaScriptStringEncode(string value)1533 public static String JavaScriptStringEncode(string value) { 1534 return JavaScriptStringEncode(value, false); 1535 } 1536 JavaScriptStringEncode(string value, bool addDoubleQuotes)1537 public static String JavaScriptStringEncode(string value, bool addDoubleQuotes) { 1538 string encoded = HttpEncoder.Current.JavaScriptStringEncode(value); 1539 return (addDoubleQuotes) ? "\"" + encoded + "\"" : encoded; 1540 } 1541 1542 /// <summary> 1543 /// Attempts to parse a co-ordinate as a double precision floating point value. 1544 /// This essentially does a Double.TryParse while disallowing specific floating point constructs such as the exponent. 1545 /// </summary> TryParseCoordinates(string value, out double doubleValue)1546 internal static bool TryParseCoordinates(string value, out double doubleValue) { 1547 var flags = NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign; 1548 return Double.TryParse(value, flags, CultureInfo.InvariantCulture, out doubleValue); 1549 } 1550 } 1551 } 1552