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 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
47 [DefaultProperty("XrdsLocation")]
48 [ToolboxData("<{0}:XrdsPublisher runat=server></{0}:XrdsPublisher>")]
49 public class XrdsPublisher
: Control
{
51 /// The view state key to ues for storing the value of the <see cref="XrdsUrl"/> property.
53 private const string XrdsUrlViewStateKey
= "XrdsUrl";
56 /// The default value for the <see cref="XrdsAdvertisement"/> property.
58 private const XrdsUrlLocations XrdsAdvertisementDefault
= XrdsUrlLocations
.HttpHeader
;
61 /// The view state key to ues for storing the value of the <see cref="XrdsAdvertisement"/> property.
63 private const string XrdsAdvertisementViewStateKey
= "XrdsAdvertisement";
66 /// The default value for the <see cref="XrdsAutoAnswer"/> property.
68 private const bool XrdsAutoAnswerDefault
= true;
71 /// The view state key to ues for storing the value of the <see cref="XrdsAutoAnswer"/> property.
73 private const string XrdsAutoAnswerViewStateKey
= "XrdsAutoAnswer";
76 /// The default value for the <see cref="Enabled"/> property.
78 private const bool EnabledDefault
= true;
81 /// The view state key to ues for storing the value of the <see cref="Enabled"/> property.
83 private const string EnabledViewStateKey
= "Enabled";
88 /// Gets or sets the location of the XRDS document.
90 [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification
= "Property grid")]
91 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
92 [Category("Behavior"), Bindable(true)]
93 public string XrdsUrl
{
95 return (string)ViewState
[XrdsUrlViewStateKey
];
99 UriUtil
.ValidateResolvableUrl(Page
, DesignMode
, value);
100 ViewState
[XrdsUrlViewStateKey
] = value;
105 /// Gets or sets where the XRDS document URL is advertised in the web response.
107 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
108 [Category("Behavior"), DefaultValue(XrdsAdvertisementDefault
), Bindable(true)]
109 [Description("Where the XRDS document URL is advertised in the web response.")]
110 public XrdsUrlLocations XrdsAdvertisement
{
112 return ViewState
[XrdsAdvertisementViewStateKey
] == null ?
113 XrdsAdvertisementDefault
: (XrdsUrlLocations
)ViewState
[XrdsAdvertisementViewStateKey
];
117 ViewState
[XrdsAdvertisementViewStateKey
] = value;
122 /// Gets or sets a value indicating whether a specially crafted YADIS
123 /// search for an XRDS document is immediately answered by this control.
125 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId
= "Xrds", Justification
= "Correct spelling")]
126 [Category("Behavior"), DefaultValue(XrdsAutoAnswerDefault
), Bindable(true)]
127 [Description("Whether XRDS requests should be immediately answered with the XRDS document if it is served by this web application.")]
128 public bool XrdsAutoAnswer
{
130 return ViewState
[XrdsAutoAnswerViewStateKey
] == null ?
131 XrdsAutoAnswerDefault
: (bool)ViewState
[XrdsAutoAnswerViewStateKey
];
135 ViewState
[XrdsAutoAnswerViewStateKey
] = value;
140 /// Gets or sets a value indicating whether the XRDS document is advertised.
142 [Category("Behavior"), DefaultValue(EnabledDefault
)]
143 public bool Enabled
{
145 return ViewState
[EnabledViewStateKey
] == null ?
146 EnabledDefault
: (bool)ViewState
[EnabledViewStateKey
];
150 ViewState
[EnabledViewStateKey
] = value;
157 /// Detects YADIS requests for the XRDS document and responds immediately
158 /// if <see cref="XrdsAutoAnswer"/> is true.
160 /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
161 protected override void OnLoad(EventArgs e
) {
168 if (!this.Page
.IsPostBack
) {
169 if (this.XrdsAutoAnswer
&& !string.IsNullOrEmpty(this.XrdsUrl
) &&
170 this.XrdsUrl
.StartsWith("~/", StringComparison
.Ordinal
)) {
171 // Check for the presence of an accept types header that is looking
172 // for the XRDS document specifically.
173 if (this.Page
.Request
.AcceptTypes
!= null && Array
.IndexOf(this.Page
.Request
.AcceptTypes
, ContentTypes
.Xrds
) >= 0) {
174 // Respond to the caller immediately with an XRDS document
175 // and avoid sending the whole web page's contents to the
176 // client since it isn't interested anyway.
177 // We do NOT simply send a 301 redirect here because that would
178 // alter the Claimed Identifier.
179 this.Page
.Server
.Transfer(this.XrdsUrl
);
186 /// Renders the HTTP Header and/or HTML HEAD tags.
188 /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
189 protected override void Render(HtmlTextWriter writer
) {
190 if (this.Enabled
&& this.Visible
&& !string.IsNullOrEmpty(this.XrdsUrl
)) {
191 Uri xrdsAddress
= new Uri(MessagingUtilities
.GetRequestUrlFromContext(), Page
.Response
.ApplyAppPathModifier(this.XrdsUrl
));
192 if ((this.XrdsAdvertisement
& XrdsUrlLocations
.HttpHeader
) != 0) {
193 Page
.Response
.AddHeader(Yadis
.Yadis
.HeaderName
, xrdsAddress
.AbsoluteUri
);
195 if ((this.XrdsAdvertisement
& XrdsUrlLocations
.HtmlMeta
) != 0) {
196 writer
.WriteBeginTag("meta");
197 writer
.WriteAttribute("http-equiv", Yadis
.Yadis
.HeaderName
);
198 writer
.WriteAttribute("content", xrdsAddress
.AbsoluteUri
);