1
//-----------------------------------------------------------------------
2 // <copyright file="XrdsPublisher.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
5 //-----------------------------------------------------------------------
7 namespace DotNetOpenAuth
{
9 using System
.Collections
.Generic
;
10 using System
.ComponentModel
;
11 using System
.Diagnostics
.CodeAnalysis
;
15 using System
.Web
.UI
.WebControls
;
16 using DotNetOpenAuth
.Messaging
;
17 using DotNetOpenAuth
.Yadis
;
20 /// The locations the YADIS protocol describes can contain a reference
21 /// to an XRDS document.
23 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
25 public enum XrdsUrlLocations
{
27 /// Indicates XRDS document referencing from an HTTP protocol header (outside the HTML).
32 /// Indicates XRDS document referencing from within an HTML page's <HEAD> tag.
37 /// Indicates XRDS document referencing in both HTTP headers and HTML HEAD tags.
43 /// An ASP.NET control that advertises an XRDS document and even responds to specially
44 /// crafted requests to retrieve it.
46 [DefaultProperty("XrdsLocation")]
47 [ToolboxData("<{0}:XrdsPublisher runat=server></{0}:XrdsPublisher>")]
48 public class XrdsPublisher
: Control
{
50 /// The view state key to ues for storing the value of the <see cref="XrdsUrl"/> property.
52 private const string XrdsUrlViewStateKey
= "XrdsUrl";
55 /// The default value for the <see cref="XrdsAdvertisement"/> property.
57 private const XrdsUrlLocations XrdsAdvertisementDefault
= XrdsUrlLocations
.HttpHeader
;
60 /// The view state key to ues for storing the value of the <see cref="XrdsAdvertisement"/> property.
62 private const string XrdsAdvertisementViewStateKey
= "XrdsAdvertisement";
65 /// The default value for the <see cref="XrdsAutoAnswer"/> property.
67 private const bool XrdsAutoAnswerDefault
= true;
70 /// The view state key to ues for storing the value of the <see cref="XrdsAutoAnswer"/> property.
72 private const string XrdsAutoAnswerViewStateKey
= "XrdsAutoAnswer";
75 /// The default value for the <see cref="Enabled"/> property.
77 private const bool EnabledDefault
= true;
80 /// The view state key to ues for storing the value of the <see cref="Enabled"/> property.
82 private const string EnabledViewStateKey
= "Enabled";
87 /// Gets or sets the location of the XRDS document.
89 [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification
= "Property grid")]
90 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
91 [Category("Behavior"), Bindable(true)]
92 public string XrdsUrl
{
94 return (string)ViewState
[XrdsUrlViewStateKey
];
98 UriUtil
.ValidateResolvableUrl(Page
, DesignMode
, value);
99 ViewState
[XrdsUrlViewStateKey
] = value;
104 /// Gets or sets where the XRDS document URL is advertised in the web response.
106 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
107 [Category("Behavior"), DefaultValue(XrdsAdvertisementDefault
), Bindable(true)]
108 [Description("Where the XRDS document URL is advertised in the web response.")]
109 public XrdsUrlLocations XrdsAdvertisement
{
111 return ViewState
[XrdsAdvertisementViewStateKey
] == null ?
112 XrdsAdvertisementDefault
: (XrdsUrlLocations
)ViewState
[XrdsAdvertisementViewStateKey
];
116 ViewState
[XrdsAdvertisementViewStateKey
] = value;
121 /// Gets or sets a value indicating whether a specially crafted YADIS
122 /// search for an XRDS document is immediately answered by this control.
124 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
125 [Category("Behavior"), DefaultValue(XrdsAutoAnswerDefault
), Bindable(true)]
126 [Description("Whether XRDS requests should be immediately answered with the XRDS document if it is served by this web application.")]
127 public bool XrdsAutoAnswer
{
129 return ViewState
[XrdsAutoAnswerViewStateKey
] == null ?
130 XrdsAutoAnswerDefault
: (bool)ViewState
[XrdsAutoAnswerViewStateKey
];
134 ViewState
[XrdsAutoAnswerViewStateKey
] = value;
139 /// Gets or sets a value indicating whether the XRDS document is advertised.
141 [Category("Behavior"), DefaultValue(EnabledDefault
)]
142 public bool Enabled
{
144 return ViewState
[EnabledViewStateKey
] == null ?
145 EnabledDefault
: (bool)ViewState
[EnabledViewStateKey
];
149 ViewState
[EnabledViewStateKey
] = value;
156 /// Detects YADIS requests for the XRDS document and responds immediately
157 /// if <see cref="XrdsAutoAnswer"/> is true.
159 /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
160 protected override void OnLoad(EventArgs e
) {
167 if (!this.Page
.IsPostBack
) {
168 if (this.XrdsAutoAnswer
&& !string.IsNullOrEmpty(this.XrdsUrl
) &&
169 this.XrdsUrl
.StartsWith("~/", StringComparison
.Ordinal
)) {
170 // Check for the presence of an accept types header that is looking
171 // for the XRDS document specifically.
172 if (this.Page
.Request
.AcceptTypes
!= null && Array
.IndexOf(this.Page
.Request
.AcceptTypes
, ContentTypes
.Xrds
) >= 0) {
173 // Respond to the caller immediately with an XRDS document
174 // and avoid sending the whole web page's contents to the
175 // client since it isn't interested anyway.
176 // We do NOT simply send a 301 redirect here because that would
177 // alter the Claimed Identifier.
178 this.Page
.Server
.Transfer(this.XrdsUrl
);
185 /// Renders the HTTP Header and/or HTML HEAD tags.
187 /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
188 protected override void Render(HtmlTextWriter writer
) {
189 if (this.Enabled
&& this.Visible
&& !string.IsNullOrEmpty(this.XrdsUrl
)) {
190 Uri xrdsAddress
= new Uri(MessagingUtilities
.GetRequestUrlFromContext(), Page
.Response
.ApplyAppPathModifier(this.XrdsUrl
));
191 if ((this.XrdsAdvertisement
& XrdsUrlLocations
.HttpHeader
) != 0) {
192 Page
.Response
.AddHeader(Yadis
.Yadis
.HeaderName
, xrdsAddress
.AbsoluteUri
);
194 if ((this.XrdsAdvertisement
& XrdsUrlLocations
.HtmlMeta
) != 0) {
195 writer
.WriteBeginTag("meta");
196 writer
.WriteAttribute("http-equiv", Yadis
.Yadis
.HeaderName
);
197 writer
.WriteAttribute("content", xrdsAddress
.AbsoluteUri
);