using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DotNetOpenId {
///
/// The locations the YADIS protocol describes can contain a reference
/// to an XRDS document.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xrds"), Flags]
public enum XrdsUrlLocations {
///
/// Indicates XRDS document referencing from an HTTP protocol header (outside the HTML).
///
HttpHeader = 0x1,
///
/// Indicates XRDS document referencing from within an HTML page's <HEAD> tag.
///
HtmlMeta = 0x2,
///
/// Indicates XRDS document referencing in both HTTP headers and HTML HEAD tags.
///
Both = 0x3
}
///
/// An ASP.NET control that advertises an XRDS document and even responds to specially
/// crafted requests to retrieve it.
///
[DefaultProperty("XrdsLocation")]
[ToolboxData("<{0}:XrdsPublisher runat=server>{0}:XrdsPublisher>")]
public class XrdsPublisher : Control {
#region Properties
const string xrdsUrlViewStateKey = "XrdsUrl";
///
/// The location of the XRDS document.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xrds"), Bindable(true)]
[Category("Behavior")]
public string XrdsUrl {
get { return (string)ViewState[xrdsUrlViewStateKey]; }
set {
RelyingParty.OpenIdTextBox.ValidateResolvableUrl(Page, DesignMode, value);
ViewState[xrdsUrlViewStateKey] = value;
}
}
const XrdsUrlLocations xrdsAdvertisementDefault = XrdsUrlLocations.HttpHeader;
const string xrdsAdvertisementViewStateKey = "XrdsAdvertisement";
///
/// Where the XRDS document URL is advertised in the web response.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xrds"), Bindable(true)]
[Category("Behavior")]
[DefaultValue(xrdsAdvertisementDefault)]
[Description("Where the XRDS document URL is advertised in the web response.")]
public XrdsUrlLocations XrdsAdvertisement {
get {
return ViewState[xrdsAdvertisementViewStateKey] == null ?
xrdsAdvertisementDefault : (XrdsUrlLocations)ViewState[xrdsAdvertisementViewStateKey];
}
set { ViewState[xrdsAdvertisementViewStateKey] = value; }
}
const bool xrdsAutoAnswerDefault = true;
const string xrdsAutoAnswerViewStateKey = "XrdsAutoAnswer";
///
/// Gets/sets whether a specially crafted YADIS search for an XRDS document is
/// immediately answered by this control.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xrds"), Bindable(true)]
[Category("Behavior")]
[DefaultValue(xrdsAutoAnswerDefault)]
[Description("Whether XRDS requests should be immediately answered with the XRDS document if it is served by this web application.")]
public bool XrdsAutoAnswer {
get {
return ViewState[xrdsAutoAnswerViewStateKey] == null ?
xrdsAutoAnswerDefault : (bool)ViewState[xrdsAutoAnswerViewStateKey];
}
set { ViewState[xrdsAutoAnswerViewStateKey] = value; }
}
const bool enabledDefault = true;
const string enabledViewStateKey = "Enabled";
///
/// Sets/gets whether the XRDS document is advertised.
///
[Category("Behavior")]
[DefaultValue(enabledDefault)]
public bool Enabled {
get {
return ViewState[enabledViewStateKey] == null ?
enabledDefault : (bool)ViewState[enabledViewStateKey];
}
set { ViewState[enabledViewStateKey] = value; }
}
#endregion
///
/// Detects YADIS requests for the XRDS document and responds immediately
/// if is true.
///
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
if (!Enabled) return;
if (!Page.IsPostBack) {
if (XrdsAutoAnswer && !string.IsNullOrEmpty(XrdsUrl) &&
XrdsUrl.StartsWith("~/", StringComparison.Ordinal)) {
// Check for the presence of an accept types header that is looking
// for the XRDS document specifically.
if (Page.Request.AcceptTypes != null &&
Array.IndexOf(Page.Request.AcceptTypes, DotNetOpenId.Yadis.ContentTypes.Xrds) >= 0) {
// Respond to the caller immediately with an XRDS document
// and avoid sending the whole web page's contents to the
// client since it isn't interested anyway.
Page.Server.Transfer(XrdsUrl);
// We do NOT simply send a 301 redirect here because that would
// alter the Claimed Identifier.
}
}
}
}
///
/// Renders the HTTP Header and/or HTML HEAD tags.
///
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings")]
protected override void Render(HtmlTextWriter writer) {
if (Enabled && Visible && !string.IsNullOrEmpty(XrdsUrl)) {
if ((XrdsAdvertisement & XrdsUrlLocations.HttpHeader) != 0) {
Page.Response.AddHeader(Yadis.Yadis.HeaderName,
new Uri(Util.GetRequestUrlFromContext(), Page.Response.ApplyAppPathModifier(XrdsUrl)).AbsoluteUri);
}
if ((XrdsAdvertisement & XrdsUrlLocations.HtmlMeta) != 0) {
writer.WriteBeginTag("meta");
writer.WriteAttribute("http-equiv", Yadis.Yadis.HeaderName);
writer.WriteAttribute("content",
new Uri(Util.GetRequestUrlFromContext(), Page.Response.ApplyAppPathModifier(XrdsUrl)).AbsoluteUri);
writer.Write("/>");
writer.WriteLine();
}
}
}
}
}