summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/Janrain.OpenId/Consumer/OpenIdLogin.cs286
-rw-r--r--source/Janrain.OpenId/Consumer/OpenIdTextBox.cs587
-rw-r--r--source/Janrain.OpenId/Janrain.OpenId.csproj14
-rw-r--r--source/Janrain.OpenId/Strings.Designer.cs72
-rw-r--r--source/Janrain.OpenId/Strings.resx123
5 files changed, 1082 insertions, 0 deletions
diff --git a/source/Janrain.OpenId/Consumer/OpenIdLogin.cs b/source/Janrain.OpenId/Consumer/OpenIdLogin.cs
new file mode 100644
index 0000000..6a37856
--- /dev/null
+++ b/source/Janrain.OpenId/Consumer/OpenIdLogin.cs
@@ -0,0 +1,286 @@
+/********************************************************
+ * Copyright (C) 2007 Andrew Arnott
+ * Released under the New BSD License
+ * License available here: http://www.opensource.org/licenses/bsd-license.php
+ * For news or support on this file: http://jmpinline.nerdbank.net/
+ ********************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.HtmlControls;
+using System.Web.Security;
+
+namespace NerdBank.OpenId.Consumer
+{
+ [DefaultProperty("OpenIdUrl")]
+ [ToolboxData("<{0}:OpenIdLogin runat=\"server\"></{0}:OpenIdLogin>")]
+ public class OpenIdLogin : OpenIdTextBox
+ {
+ Panel panel;
+ Button loginButton;
+ HtmlGenericControl label;
+ RequiredFieldValidator requiredValidator;
+ RegularExpressionValidator uriFormatValidator;
+ Label examplePrefixLabel;
+ Label exampleUrlLabel;
+ HyperLink registerLink;
+
+ protected override void CreateChildControls()
+ {
+ // Don't call base.CreateChildControls(). This would add the WrappedTextBox
+ // to the Controls collection, which would implicitly remove it from the table
+ // we have already added it to.
+
+ // Just add the panel we've assembled earlier.
+ Controls.Add(panel);
+
+ if (ShouldBeFocused)
+ WrappedTextBox.Focus();
+ }
+
+ protected override void InitializeControls()
+ {
+ base.InitializeControls();
+
+ panel = new Panel();
+
+ Table table = new Table();
+ TableRow row1, row2;
+ TableCell cell;
+ table.Rows.Add(row1 = new TableRow());
+ table.Rows.Add(row2 = new TableRow());
+
+ // top row, left cell
+ cell = new TableCell();
+ label = new HtmlGenericControl("label");
+ label.InnerText = labelTextDefault;
+ cell.Controls.Add(label);
+ row1.Cells.Add(cell);
+
+ // top row, middle cell
+ cell = new TableCell();
+ cell.Controls.Add(WrappedTextBox);
+ row1.Cells.Add(cell);
+
+ // top row, right cell
+ cell = new TableCell();
+ loginButton = new Button();
+ loginButton.ID = "loginButton";
+ loginButton.Text = buttonTextDefault;
+ loginButton.ToolTip = buttonToolTipDefault;
+ loginButton.Click += new EventHandler(loginButton_Click);
+ loginButton.ValidationGroup = validationGroupDefault;
+#if !Mono
+ panel.DefaultButton = loginButton.ID;
+#endif
+ cell.Controls.Add(loginButton);
+ row1.Cells.Add(cell);
+
+ // bottom row, left cell
+ row2.Cells.Add(new TableCell());
+
+ // bottom row, middle cell
+ cell = new TableCell();
+ cell.Style[HtmlTextWriterStyle.Color] = "gray";
+ cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
+ requiredValidator = new RequiredFieldValidator();
+ requiredValidator.ErrorMessage = requiredTextDefault + requiredTextSuffix;
+ requiredValidator.Display = ValidatorDisplay.Dynamic;
+ requiredValidator.ControlToValidate = WrappedTextBox.ID;
+ requiredValidator.ValidationGroup = validationGroupDefault;
+ cell.Controls.Add(requiredValidator);
+ uriFormatValidator = new RegularExpressionValidator();
+ uriFormatValidator.ErrorMessage = uriFormatTextDefault + requiredTextSuffix;
+ uriFormatValidator.ValidationExpression = @"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
+ uriFormatValidator.Display = ValidatorDisplay.Dynamic;
+ uriFormatValidator.ControlToValidate = WrappedTextBox.ID;
+ uriFormatValidator.ValidationGroup = validationGroupDefault;
+ cell.Controls.Add(uriFormatValidator);
+ examplePrefixLabel = new Label();
+ examplePrefixLabel.Text = examplePrefixDefault;
+ cell.Controls.Add(examplePrefixLabel);
+ cell.Controls.Add(new LiteralControl(" "));
+ exampleUrlLabel = new Label();
+ exampleUrlLabel.Font.Bold = true;
+ exampleUrlLabel.Text = exampleUrlDefault;
+ cell.Controls.Add(exampleUrlLabel);
+ row2.Cells.Add(cell);
+
+ // bottom row, right cell
+ cell = new TableCell();
+ cell.Style[HtmlTextWriterStyle.Color] = "gray";
+ cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
+ cell.Style[HtmlTextWriterStyle.TextAlign] = "center";
+ registerLink = new HyperLink();
+ registerLink.Text = registerTextDefault;
+ registerLink.ToolTip = registerToolTipDefault;
+ registerLink.NavigateUrl = registerUrlDefault;
+ cell.Controls.Add(registerLink);
+ row2.Cells.Add(cell);
+
+ panel.Controls.Add(table);
+ }
+
+ protected override void RenderChildren(HtmlTextWriter writer)
+ {
+ if (!this.DesignMode)
+ label.Attributes["for"] = WrappedTextBox.ClientID;
+
+ base.RenderChildren(writer);
+ }
+
+ #region Properties
+ const string labelTextDefault = "OpenID Login:";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(labelTextDefault)]
+ [Localizable(true)]
+ public string LabelText
+ {
+ get { return label.InnerText; }
+ set { label.InnerText = value; }
+ }
+
+ const string examplePrefixDefault = "Example:";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(examplePrefixDefault)]
+ [Localizable(true)]
+ public string ExamplePrefix
+ {
+ get { return examplePrefixLabel.Text; }
+ set { examplePrefixLabel.Text = value; }
+ }
+
+ const string exampleUrlDefault = "http://your.name.myopenid.com";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(exampleUrlDefault)]
+ [Localizable(true)]
+ public string ExampleUrl
+ {
+ get { return exampleUrlLabel.Text; }
+ set { exampleUrlLabel.Text = value; }
+ }
+
+ const string requiredTextSuffix = "<br/>";
+ const string requiredTextDefault = "Provide an OpenID first.";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(requiredTextDefault)]
+ [Localizable(true)]
+ public string RequiredText
+ {
+ get { return requiredValidator.Text.Substring(requiredValidator.Text.Length - requiredTextSuffix.Length); }
+ set { requiredValidator.Text = value + requiredTextSuffix; }
+ }
+
+ const string uriFormatTextDefault = "Invalid OpenID URL.";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(uriFormatTextDefault)]
+ [Localizable(true)]
+ public string UriFormatText
+ {
+ get { return uriFormatValidator.Text.Substring(uriFormatValidator.Text.Length - requiredTextSuffix.Length); }
+ set { uriFormatValidator.Text = value + requiredTextSuffix; }
+ }
+
+ const string registerTextDefault = "register";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(registerTextDefault)]
+ [Localizable(true)]
+ public string RegisterText
+ {
+ get { return registerLink.Text; }
+ set { registerLink.Text = value; }
+ }
+
+ const string registerUrlDefault = "https://www.myopenid.com/signup";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(registerUrlDefault)]
+ [Localizable(true)]
+ public string RegisterUrl
+ {
+ get { return registerLink.NavigateUrl; }
+ set { registerLink.NavigateUrl = value; }
+ }
+
+ const string registerToolTipDefault = "Sign up free for an OpenID with MyOpenID now.";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(registerToolTipDefault)]
+ [Localizable(true)]
+ public string RegisterToolTip
+ {
+ get { return registerLink.ToolTip; }
+ set { registerLink.ToolTip = value; }
+ }
+
+ const string buttonTextDefault = "Login »";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(buttonTextDefault)]
+ [Localizable(true)]
+ public string ButtonText
+ {
+ get { return loginButton.Text; }
+ set { loginButton.Text = value; }
+ }
+
+ const string buttonToolTipDefault = "Account login";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(buttonToolTipDefault)]
+ [Localizable(true)]
+ public string ButtonToolTip
+ {
+ get { return loginButton.ToolTip; }
+ set { loginButton.ToolTip = value; }
+ }
+
+ const string validationGroupDefault = "OpenIdLogin";
+ [Category("Behavior")]
+ [DefaultValue(validationGroupDefault)]
+ public string ValidationGroup
+ {
+ get { return requiredValidator.ValidationGroup; }
+ set
+ {
+ requiredValidator.ValidationGroup = value;
+ loginButton.ValidationGroup = value;
+ }
+ }
+ #endregion
+
+ #region Event handlers
+ void loginButton_Click(object sender, EventArgs e)
+ {
+ if (!Page.IsValid) return;
+ if (OnLoggingIn(new Uri(Text)))
+ Login();
+ }
+
+ #endregion
+
+ #region Events
+ public event EventHandler<OpenIdTextBox.OpenIdEventArgs> LoggingIn;
+ protected virtual bool OnLoggingIn(Uri openIdUri)
+ {
+ EventHandler<OpenIdTextBox.OpenIdEventArgs> loggingIn = LoggingIn;
+ OpenIdTextBox.OpenIdEventArgs args = new OpenIdTextBox.OpenIdEventArgs(openIdUri,
+ OpenIdTextBox.OpenIdProfileFields.Empty);
+ if (loggingIn != null)
+ loggingIn(this, args);
+ return !args.Cancel;
+ }
+ #endregion
+ }
+}
diff --git a/source/Janrain.OpenId/Consumer/OpenIdTextBox.cs b/source/Janrain.OpenId/Consumer/OpenIdTextBox.cs
new file mode 100644
index 0000000..43b35ce
--- /dev/null
+++ b/source/Janrain.OpenId/Consumer/OpenIdTextBox.cs
@@ -0,0 +1,587 @@
+/********************************************************
+ * Copyright (C) 2007 Andrew Arnott
+ * Released under the New BSD License
+ * License available here: http://www.opensource.org/licenses/bsd-license.php
+ * For news or support on this file: http://jmpinline.nerdbank.net/
+ ********************************************************/
+
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Text;
+using System.Net.Mail;
+using System.Web;
+using System.Web.Security;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+
+using Janrain.OpenId;
+using Janrain.OpenId.Consumer;
+using Janrain.OpenId.Store;
+
+namespace NerdBank.OpenId.Consumer
+{
+ [DefaultProperty("Text")]
+ [ToolboxData("<{0}:OpenIdTextBox runat=\"server\"></{0}:OpenIdTextBox>")]
+ public class OpenIdTextBox : CompositeControl
+ {
+ public OpenIdTextBox()
+ {
+ InitializeControls();
+ }
+
+ TextBox wrappedTextBox;
+ protected TextBox WrappedTextBox
+ {
+ get { return wrappedTextBox; }
+ }
+
+ protected override void CreateChildControls()
+ {
+ base.CreateChildControls();
+
+ Controls.Add(wrappedTextBox);
+ if (ShouldBeFocused)
+ WrappedTextBox.Focus();
+ }
+
+ protected virtual void InitializeControls()
+ {
+ wrappedTextBox = new TextBox();
+ wrappedTextBox.ID = "wrappedTextBox";
+ wrappedTextBox.CssClass = cssClassDefault;
+ wrappedTextBox.Columns = columnsDefault;
+ wrappedTextBox.Text = text;
+ }
+
+ protected bool ShouldBeFocused;
+ public override void Focus()
+ {
+ if (Controls.Count == 0)
+ ShouldBeFocused = true;
+ else
+ WrappedTextBox.Focus();
+ }
+
+ #region Properties
+ const string textDefault = "";
+ string text = textDefault;
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue("")]
+ public string Text
+ {
+ get { return (WrappedTextBox != null) ? WrappedTextBox.Text : text; }
+ set
+ {
+ text = value;
+ if (WrappedTextBox != null) WrappedTextBox.Text = value;
+ }
+ }
+
+ const string cssClassDefault = "openid";
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(cssClassDefault)]
+ public override string CssClass
+ {
+ get { return WrappedTextBox.CssClass; }
+ set { WrappedTextBox.CssClass = value; }
+ }
+
+ const int columnsDefault = 40;
+ [Bindable(true)]
+ [Category("Appearance")]
+ [DefaultValue(columnsDefault)]
+ public int Columns
+ {
+ get { return WrappedTextBox.Columns; }
+ set { WrappedTextBox.Columns = value; }
+ }
+
+ public enum ProfileRequest
+ {
+ NoRequest,
+ Request,
+ Require,
+ }
+
+ const string requestNicknameViewStateKey = "RequestNickname";
+ const ProfileRequest requestNicknameDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestNicknameDefault)]
+ public ProfileRequest RequestNickname
+ {
+ get { return (ProfileRequest)(ViewState[requestNicknameViewStateKey] ?? requestNicknameDefault); }
+ set { ViewState[requestNicknameViewStateKey] = value; }
+ }
+
+ const string requestEmailViewStateKey = "RequestEmail";
+ const ProfileRequest requestEmailDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestEmailDefault)]
+ public ProfileRequest RequestEmail
+ {
+ get { return (ProfileRequest)(ViewState[requestEmailViewStateKey] ?? requestEmailDefault); }
+ set { ViewState[requestEmailViewStateKey] = value; }
+ }
+
+ const string requestFullNameViewStateKey = "RequestFullName";
+ const ProfileRequest requestFullNameDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestFullNameDefault)]
+ public ProfileRequest RequestFullName
+ {
+ get { return (ProfileRequest)(ViewState[requestFullNameViewStateKey] ?? requestFullNameDefault); }
+ set { ViewState[requestFullNameViewStateKey] = value; }
+ }
+
+ const string requestBirthdateViewStateKey = "RequestBirthday";
+ const ProfileRequest requestBirthdateDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestBirthdateDefault)]
+ public ProfileRequest RequestBirthdate
+ {
+ get { return (ProfileRequest)(ViewState[requestBirthdateViewStateKey] ?? requestBirthdateDefault); }
+ set { ViewState[requestBirthdateViewStateKey] = value; }
+ }
+
+ const string requestGenderViewStateKey = "RequestGender";
+ const ProfileRequest requestGenderDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestGenderDefault)]
+ public ProfileRequest RequestGender
+ {
+ get { return (ProfileRequest)(ViewState[requestGenderViewStateKey] ?? requestGenderDefault); }
+ set { ViewState[requestGenderViewStateKey] = value; }
+ }
+
+ const string requestPostalCodeViewStateKey = "RequestPostalCode";
+ const ProfileRequest requestPostalCodeDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestPostalCodeDefault)]
+ public ProfileRequest RequestPostalCode
+ {
+ get { return (ProfileRequest)(ViewState[requestPostalCodeViewStateKey] ?? requestPostalCodeDefault); }
+ set { ViewState[requestPostalCodeViewStateKey] = value; }
+ }
+
+ const string requestCountryViewStateKey = "RequestCountry";
+ const ProfileRequest requestCountryDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestCountryDefault)]
+ public ProfileRequest RequestCountry
+ {
+ get { return (ProfileRequest)(ViewState[requestCountryViewStateKey] ?? requestCountryDefault); }
+ set { ViewState[requestCountryViewStateKey] = value; }
+ }
+
+ const string requestLanguageViewStateKey = "RequestLanguage";
+ const ProfileRequest requestLanguageDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestLanguageDefault)]
+ public ProfileRequest RequestLanguage
+ {
+ get { return (ProfileRequest)(ViewState[requestLanguageViewStateKey] ?? requestLanguageDefault); }
+ set { ViewState[requestLanguageViewStateKey] = value; }
+ }
+
+ const string requestTimeZoneViewStateKey = "RequestTimeZone";
+ const ProfileRequest requestTimeZoneDefault = ProfileRequest.NoRequest;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(requestTimeZoneDefault)]
+ public ProfileRequest RequestTimeZone
+ {
+ get { return (ProfileRequest)(ViewState[requestTimeZoneViewStateKey] ?? requestTimeZoneDefault); }
+ set { ViewState[requestTimeZoneViewStateKey] = value; }
+ }
+
+ const string policyUrlViewStateKey = "PolicyUrl";
+ const string policyUrlDefault = "";
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(policyUrlDefault)]
+ public string PolicyUrl
+ {
+ get { return (string)ViewState[policyUrlViewStateKey] ?? policyUrlDefault; }
+ set { ViewState[policyUrlViewStateKey] = value; }
+ }
+
+ const string enableRequestProfileViewStateKey = "EnableRequestProfile";
+ const bool enableRequestProfileDefault = true;
+ [Bindable(true)]
+ [Category("Profile")]
+ [DefaultValue(enableRequestProfileDefault)]
+ public bool EnableRequestProfile
+ {
+ get { return (bool)(ViewState[enableRequestProfileViewStateKey] ?? enableRequestProfileDefault); }
+ set { ViewState[enableRequestProfileViewStateKey] = value; }
+ }
+ #endregion
+
+ #region Properties to hide
+ [Browsable(false), Bindable(false)]
+ public override System.Drawing.Color ForeColor
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override System.Drawing.Color BackColor
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override System.Drawing.Color BorderColor
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override Unit BorderWidth
+ {
+ get { return Unit.Empty; }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override BorderStyle BorderStyle
+ {
+ get { return BorderStyle.None; }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override FontInfo Font
+ {
+ get { return null; }
+ }
+ [Browsable(false), Bindable(false)]
+ public override Unit Height
+ {
+ get { return Unit.Empty; }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override Unit Width
+ {
+ get { return Unit.Empty; }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override string ToolTip
+ {
+ get { return string.Empty; }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override string SkinID
+ {
+ get { return string.Empty; }
+ set { throw new NotSupportedException(); }
+ }
+ [Browsable(false), Bindable(false)]
+ public override bool EnableTheming
+ {
+ get { return false; }
+ set { throw new NotSupportedException(); }
+ }
+ #endregion
+
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+
+ try
+ {
+ if (!Page.IsPostBack && Page.Request.QueryString["openid.mode"] != null)
+ {
+ Janrain.OpenId.Consumer.Consumer consumer =
+ new Janrain.OpenId.Consumer.Consumer(Page.Session, MemoryStore.GetInstance());
+
+ ConsumerResponse resp = consumer.Complete(Page.Request.QueryString);
+ OnLoggedIn(resp.IdentityUrl, parseProfileFields(Page.Request.QueryString));
+ }
+ }
+ catch (FailureException fexc)
+ {
+ OnError(fexc);
+ }
+ catch (CancelException cex)
+ {
+ OnError(cex);
+ }
+ }
+
+ public void Login()
+ {
+ if (string.IsNullOrEmpty(Text))
+ throw new InvalidOperationException(Janrain.OpenId.Strings.OpenIdTextBoxEmpty);
+
+ Janrain.OpenId.Consumer.Consumer consumer =
+ new Janrain.OpenId.Consumer.Consumer(Page.Session, MemoryStore.GetInstance());
+
+ Uri userUri = UriUtil.NormalizeUri(Text);
+ // Initiate openid request
+ AuthRequest request = consumer.Begin(userUri);
+ if (EnableRequestProfile) addProfileArgs(request);
+
+ // Build the trust root
+ UriBuilder builder = new UriBuilder(Page.Request.Url.AbsoluteUri);
+ builder.Query = null;
+ builder.Password = null;
+ builder.UserName = null;
+ builder.Fragment = null;
+ builder.Path = Page.Request.ApplicationPath;
+ string trustRoot = builder.ToString();
+
+ // Build the return_to URL
+ builder = new UriBuilder(Page.Request.Url.AbsoluteUri);
+ NameValueCollection col = new NameValueCollection();
+ if (!string.IsNullOrEmpty(Page.Request.QueryString["ReturnUrl"]))
+ col["ReturnUrl"] = Page.Request.QueryString["ReturnUrl"];
+ builder.Query = UriUtil.CreateQueryString(col);
+ Uri returnTo = new Uri(builder.ToString(), true);
+
+ Uri redirectUrl = request.CreateRedirect(trustRoot, returnTo, AuthRequest.Mode.SETUP);
+ Page.Response.Redirect(redirectUrl.AbsoluteUri);
+ }
+
+ void addProfileArgs(AuthRequest request)
+ {
+ request.ExtraArgs.Add("openid.sreg.required",
+ string.Join(",", assembleProfileFields(ProfileRequest.Require)));
+ request.ExtraArgs.Add("openid.sreg.optional",
+ string.Join(",", assembleProfileFields(ProfileRequest.Request)));
+ request.ExtraArgs.Add("openid.sreg.policy_url", PolicyUrl);
+ }
+
+ string[] assembleProfileFields(ProfileRequest level)
+ {
+ List<string> fields = new List<string>(10);
+ if (RequestNickname == level)
+ fields.Add("nickname");
+ if (RequestEmail == level)
+ fields.Add("email");
+ if (RequestFullName == level)
+ fields.Add("fullname");
+ if (RequestBirthdate == level)
+ fields.Add("dob");
+ if (RequestGender == level)
+ fields.Add("gender");
+ if (RequestPostalCode == level)
+ fields.Add("postcode");
+ if (RequestCountry == level)
+ fields.Add("country");
+ if (RequestLanguage == level)
+ fields.Add("language");
+ if (RequestTimeZone == level)
+ fields.Add("timezone");
+
+ return fields.ToArray();
+ }
+ OpenIdProfileFields parseProfileFields(NameValueCollection queryString)
+ {
+ OpenIdProfileFields fields = new OpenIdProfileFields();
+ if (RequestNickname > ProfileRequest.NoRequest)
+ fields.Nickname = queryString["openid.sreg.nickname"];
+ if (RequestEmail > ProfileRequest.NoRequest &&
+ !string.IsNullOrEmpty(queryString["openid.sreg.email"]))
+ fields.Email = new MailAddress(queryString["openid.sreg.email"]);
+ if (RequestFullName > ProfileRequest.NoRequest)
+ fields.Fullname = queryString["openid.sreg.fullname"];
+ if (RequestBirthdate > ProfileRequest.NoRequest)
+ {
+ DateTime birthdate;
+ DateTime.TryParse(queryString["openid.sreg.dob"], out birthdate);
+ fields.Birthdate = birthdate;
+ }
+ if (RequestGender > ProfileRequest.NoRequest)
+ switch (queryString["openid.sreg.gender"])
+ {
+ case "M": fields.Gender = Gender.Male; break;
+ case "F": fields.Gender = Gender.Female; break;
+ }
+ if (RequestPostalCode > ProfileRequest.NoRequest)
+ fields.PostalCode = queryString["openid.sreg.postcode"];
+ if (RequestCountry > ProfileRequest.NoRequest)
+ fields.Country = queryString["openid.sreg.country"];
+ string cultureString = "";
+ if (RequestLanguage > ProfileRequest.NoRequest)
+ {
+ fields.Language = queryString["openid.sreg.language"];
+
+ if (!string.IsNullOrEmpty(fields.Language))
+ {
+ cultureString = fields.Language;
+ if (!string.IsNullOrEmpty(fields.Country))
+ cultureString += "-" + fields.Country;
+ fields.Culture = CultureInfo.GetCultureInfo(cultureString);
+ }
+ }
+ if (RequestTimeZone > ProfileRequest.NoRequest)
+ fields.TimeZone = queryString["openid.sreg.timezone"];
+ return fields;
+ }
+
+ public enum Gender
+ {
+ Male,
+ Female,
+ }
+
+ public struct OpenIdProfileFields
+ {
+ internal static OpenIdProfileFields Empty = new OpenIdProfileFields();
+
+ private string nickname;
+ public string Nickname
+ {
+ get { return nickname; }
+ set { nickname = value; }
+ }
+
+ private MailAddress email;
+ public MailAddress Email
+ {
+ get { return email; }
+ set { email = value; }
+ }
+
+ private string fullName;
+ public string Fullname
+ {
+ get { return fullName; }
+ set { fullName = value; }
+ }
+
+ private DateTime? birthdate;
+ public DateTime? Birthdate
+ {
+ get { return birthdate; }
+ set { birthdate = value; }
+ }
+
+ private Gender? gender;
+ public Gender? Gender
+ {
+ get { return gender; }
+ set { gender = value; }
+ }
+
+ private string postalCode;
+ public string PostalCode
+ {
+ get { return postalCode; }
+ set { postalCode = value; }
+ }
+
+ private string country;
+ public string Country
+ {
+ get { return country; }
+ set { country = value; }
+ }
+
+ private string language;
+ public string Language
+ {
+ get { return language; }
+ set { language = value; }
+ }
+
+ private CultureInfo culture;
+ public CultureInfo Culture
+ {
+ get { return culture; }
+ set { culture = value; }
+ }
+
+ private string timeZone;
+ public string TimeZone
+ {
+ get { return timeZone; }
+ set { timeZone = value; }
+ }
+ }
+
+ #region Events
+ public class OpenIdEventArgs : EventArgs
+ {
+ public OpenIdEventArgs(Uri openIdUri, OpenIdProfileFields profileFields)
+ {
+ this.openIdUri = openIdUri;
+ this.profileFields = profileFields;
+ }
+ private Uri openIdUri;
+ /// <summary>
+ /// The OpenID url of the authenticating user.
+ /// </summary>
+ public Uri OpenIdUri
+ {
+ get { return openIdUri; }
+ }
+ private bool cancel;
+ /// <summary>
+ /// Cancels the OpenID authentication and/or login process.
+ /// </summary>
+ public bool Cancel
+ {
+ get { return cancel; }
+ set { cancel = value; }
+ }
+
+ private OpenIdProfileFields profileFields;
+ public OpenIdProfileFields ProfileFields
+ {
+ get { return profileFields; }
+ }
+ }
+ public event EventHandler<OpenIdEventArgs> LoggedIn;
+ protected virtual void OnLoggedIn(Uri openIdUri, OpenIdProfileFields profileFields)
+ {
+ EventHandler<OpenIdEventArgs> loggedIn = LoggedIn;
+ OpenIdEventArgs args = new OpenIdEventArgs(openIdUri, profileFields);
+ if (loggedIn != null)
+ loggedIn(this, args);
+ if (!args.Cancel)
+ FormsAuthentication.RedirectFromLoginPage(openIdUri.AbsoluteUri, false);
+ }
+
+ #endregion
+ #region Error handling
+ public class ErrorEventArgs : EventArgs
+ {
+ public ErrorEventArgs(string errorMessage, Exception errorException)
+ {
+ ErrorMessage = errorMessage;
+ ErrorException = errorException;
+ }
+ public string ErrorMessage;
+ public Exception ErrorException;
+ }
+ public event EventHandler<ErrorEventArgs> Error;
+ protected virtual void OnError(Exception errorException)
+ {
+ if (errorException == null)
+ throw new ArgumentNullException("errorException");
+
+ EventHandler<ErrorEventArgs> error = Error;
+ if (error != null)
+ error(this, new ErrorEventArgs(errorException.Message, errorException));
+ }
+ #endregion
+ }
+}
diff --git a/source/Janrain.OpenId/Janrain.OpenId.csproj b/source/Janrain.OpenId/Janrain.OpenId.csproj
index 861f91a..f9eca29 100644
--- a/source/Janrain.OpenId/Janrain.OpenId.csproj
+++ b/source/Janrain.OpenId/Janrain.OpenId.csproj
@@ -45,6 +45,8 @@
<Compile Include="Consumer\FetchResponse.cs" />
<Compile Include="Consumer\GenericConsumer.cs" />
<Compile Include="Consumer\Manager.cs" />
+ <Compile Include="Consumer\OpenIdLogin.cs" />
+ <Compile Include="Consumer\OpenIdTextBox.cs" />
<Compile Include="Consumer\ServiceEndpoint.cs" />
<Compile Include="Consumer\SimpleFetcher.cs" />
<Compile Include="CryptUtil.cs" />
@@ -80,6 +82,11 @@
<Compile Include="Server\WebResponse.cs" />
<Compile Include="Store\IAssociationStore.cs" />
<Compile Include="Store\MemoryStore.cs" />
+ <Compile Include="Strings.Designer.cs">
+ <DependentUpon>Strings.resx</DependentUpon>
+ <DesignTime>True</DesignTime>
+ <AutoGen>True</AutoGen>
+ </Compile>
<Compile Include="Util.cs" />
<Compile Include="Yadis\AcceptHeader.cs" />
<Compile Include="Yadis\ByteParser.cs" />
@@ -93,6 +100,13 @@
<Compile Include="Yadis\XrdNode.cs" />
<Compile Include="Yadis\Yadis.cs" />
</ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Strings.resx">
+ <SubType>Designer</SubType>
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Strings.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/source/Janrain.OpenId/Strings.Designer.cs b/source/Janrain.OpenId/Strings.Designer.cs
new file mode 100644
index 0000000..3c83a31
--- /dev/null
+++ b/source/Janrain.OpenId/Strings.Designer.cs
@@ -0,0 +1,72 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.312
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Janrain.OpenId {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Strings() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Janrain.OpenId.Strings", typeof(Strings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to No OpenId url is provided..
+ /// </summary>
+ internal static string OpenIdTextBoxEmpty {
+ get {
+ return ResourceManager.GetString("OpenIdTextBoxEmpty", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/source/Janrain.OpenId/Strings.resx b/source/Janrain.OpenId/Strings.resx
new file mode 100644
index 0000000..1eea010
--- /dev/null
+++ b/source/Janrain.OpenId/Strings.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="OpenIdTextBoxEmpty" xml:space="preserve">
+ <value>No OpenId url is provided.</value>
+ </data>
+</root> \ No newline at end of file