Added the XrdsPublisher ASP.NET control.
[dotnetoauth.git] / src / DotNetOpenAuth / UriUtil.cs
blob3ef8d50f93d029074eeec3519ac61841c93d3795
1 //-----------------------------------------------------------------------
2 // <copyright file="UriUtil.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
4 // </copyright>
5 //-----------------------------------------------------------------------
7 namespace DotNetOpenAuth {
8 using System;
9 using System.Collections.Specialized;
10 using System.Diagnostics.CodeAnalysis;
11 using System.Linq;
12 using System.Text.RegularExpressions;
13 using System.Web;
14 using System.Web.UI;
15 using DotNetOpenAuth.Messaging;
17 /// <summary>
18 /// Utility methods for working with URIs.
19 /// </summary>
20 internal static class UriUtil {
21 /// <summary>
22 /// Tests a URI for the presence of an OAuth payload.
23 /// </summary>
24 /// <param name="uri">The URI to test.</param>
25 /// <returns>True if the URI contains an OAuth message.</returns>
26 internal static bool QueryStringContainsOAuthParameters(Uri uri) {
27 if (uri == null) {
28 return false;
31 NameValueCollection nvc = HttpUtility.ParseQueryString(uri.Query);
32 return nvc.Keys.OfType<string>().Any(key => key.StartsWith(OAuth.Protocol.V10.ParameterPrefix, StringComparison.Ordinal));
35 /// <summary>
36 /// Determines whether some <see cref="Uri"/> is using HTTPS.
37 /// </summary>
38 /// <param name="uri">The Uri being tested for security.</param>
39 /// <returns>
40 /// <c>true</c> if the URI represents an encrypted request; otherwise, <c>false</c>.
41 /// </returns>
42 internal static bool IsTransportSecure(this Uri uri) {
43 if (uri == null) {
44 throw new ArgumentNullException("uri");
47 return string.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase);
50 /// <summary>
51 /// Equivalent to UriBuilder.ToString() but omits port # if it may be implied.
52 /// Equivalent to UriBuilder.Uri.ToString(), but doesn't throw an exception if the Host has a wildcard.
53 /// </summary>
54 /// <param name="builder">The UriBuilder to render as a string.</param>
55 /// <returns>The string version of the Uri.</returns>
56 internal static string ToStringWithImpliedPorts(this UriBuilder builder) {
57 ErrorUtilities.VerifyArgumentNotNull(builder, "builder");
59 // We only check for implied ports on HTTP and HTTPS schemes since those
60 // are the only ones supported by OpenID anyway.
61 if ((builder.Port == 80 && string.Equals(builder.Scheme, "http", StringComparison.OrdinalIgnoreCase)) ||
62 (builder.Port == 443 && string.Equals(builder.Scheme, "https", StringComparison.OrdinalIgnoreCase))) {
63 // An implied port may be removed.
64 string url = builder.ToString();
66 // Be really careful to only remove the first :80 or :443 so we are guaranteed
67 // we're removing only the port (and not something in the query string that
68 // looks like a port.
69 return Regex.Replace(url, @"^(https?://[^:]+):\d+", m => m.Groups[1].Value, RegexOptions.IgnoreCase);
70 } else {
71 // The port must be explicitly given anyway.
72 return builder.ToString();
76 /// <summary>
77 /// Validates that a URL will be resolvable at runtime.
78 /// </summary>
79 /// <param name="page">The page hosting the control that receives this URL as a property.</param>
80 /// <param name="designMode">If set to <c>true</c> the page is in design-time mode rather than runtime mode.</param>
81 /// <param name="value">The URI to check.</param>
82 /// <exception cref="UriFormatException">Thrown if the given URL is not a valid, resolvable URI.</exception>
83 [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Just to throw an exception on invalid input.")]
84 internal static void ValidateResolvableUrl(Page page, bool designMode, string value) {
85 if (string.IsNullOrEmpty(value)) {
86 return;
89 if (page != null && !designMode) {
90 // Validate new value by trying to construct a Realm object based on it.
91 new Uri(page.Request.Url, page.ResolveUrl(value)); // throws an exception on failure.
92 } else {
93 // We can't fully test it, but it should start with either ~/ or a protocol.
94 if (Regex.IsMatch(value, @"^https?://")) {
95 new Uri(value); // make sure it's fully-qualified, but ignore wildcards
96 } else if (value.StartsWith("~/", StringComparison.Ordinal)) {
97 // this is valid too
98 } else {
99 throw new UriFormatException();