Merge pull request #1506 from akoeplinger/fix-paste-test
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / PasswordRecovery.cs
1 //
2 // System.Web.UI.WebControls.PasswordRecovery.cs
3 //
4 // Authors:
5 //      Vladimir Krasnov (vladimirk@mainsoft.com)
6 //
7 // (C) 2006 Mainsoft, Inc (http://www.mainsoft.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29
30 using System;
31 using System.Net.Mail;
32 using System.Collections;
33 using System.Collections.Specialized;
34 using System.ComponentModel;
35 using System.Drawing.Design;
36 using System.Web;
37 using System.Web.UI;
38 using System.Web.Security;
39
40 namespace System.Web.UI.WebControls
41 {
42         [Bindable (false)]
43         [DefaultEvent ("SendingMail")]
44         [Designer ("System.Web.UI.Design.WebControls.PasswordRecoveryDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45         public class PasswordRecovery : CompositeControl
46         , IRenderOuterTable
47         {
48                 static readonly object answerLookupErrorEvent = new object ();
49                 static readonly object sendingMailEvent = new object ();
50                 static readonly object sendMailErrorEvent = new object ();
51                 static readonly object userLookupErrorEvent = new object ();
52                 static readonly object verifyingAnswerEvent = new object ();
53                 static readonly object verifyingUserEvent = new object ();
54                 
55                 public static readonly string SubmitButtonCommandName = "Submit";
56                 bool renderOuterTable = true;
57                 TableItemStyle _failureTextStyle;
58                 TableItemStyle _hyperLinkStyle;
59                 TableItemStyle _instructionTextStyle;
60                 TableItemStyle _labelStyle;
61                 Style _submitButtonStyle;
62                 TableItemStyle _successTextStyle;
63                 Style _textBoxStyle;
64                 TableItemStyle _titleTextStyle;
65                 Style _validatorTextStyle;
66
67                 MailDefinition _mailDefinition;
68                 MembershipProvider _provider = null;
69
70                 ITemplate _questionTemplate = null;
71                 ITemplate _successTemplate = null;
72                 ITemplate _userNameTemplate = null;
73
74                 QuestionContainer _questionTemplateContainer = null;
75                 SuccessContainer _successTemplateContainer = null;
76                 UserNameContainer _userNameTemplateContainer = null;
77
78                 PasswordReciveryStep _currentStep = PasswordReciveryStep.StepUserName;
79
80                 string _username = null;
81                 string _answer = null;
82
83                 EventHandlerList events = new EventHandlerList ();
84
85 #region Events
86                 public event EventHandler AnswerLookupError {
87                         add { events.AddHandler (answerLookupErrorEvent, value); }
88                         remove { events.RemoveHandler (answerLookupErrorEvent, value); }
89                 }
90                 
91                 public event MailMessageEventHandler SendingMail {
92                         add { events.AddHandler (sendingMailEvent, value); }
93                         remove { events.RemoveHandler (sendingMailEvent, value); }
94                 }
95                 
96                 public event SendMailErrorEventHandler SendMailError {
97                         add { events.AddHandler (sendMailErrorEvent, value); }
98                         remove { events.RemoveHandler (sendMailErrorEvent, value); }
99                 }
100                 
101                 public event EventHandler UserLookupError {
102                         add { events.AddHandler (userLookupErrorEvent, value); }
103                         remove { events.RemoveHandler (userLookupErrorEvent, value); }
104                 }
105                 
106                 public event LoginCancelEventHandler VerifyingAnswer {
107                         add { events.AddHandler (verifyingAnswerEvent, value); }
108                         remove { events.RemoveHandler (verifyingAnswerEvent, value); }
109                 }
110                 
111                 public event LoginCancelEventHandler VerifyingUser {
112                         add { events.AddHandler (verifyingUserEvent, value); }
113                         remove { events.RemoveHandler (verifyingUserEvent, value); }
114                 }
115 #endregion
116
117                 public PasswordRecovery ()
118                 {
119                 }
120
121                 [Browsable (false)]
122                 [Filterable (false)]
123                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
124                 [Themeable (false)]
125                 public virtual string Answer {
126                         get { return _answer != null ? _answer : string.Empty; }
127                 }
128
129                 [Localizable (true)]
130                 public virtual string AnswerLabelText
131                 {
132                         get { return ViewState.GetString ("AnswerLabelText", "Answer:"); }
133                         set { ViewState ["AnswerLabelText"] = value; }
134                 }
135
136                 [Localizable (true)]
137                 public virtual string AnswerRequiredErrorMessage
138                 {
139                         get { return ViewState.GetString ("AnswerRequiredErrorMessage", "Answer is required."); }
140                         set { ViewState ["AnswerRequiredErrorMessage"] = value; }
141                 }
142
143                 [DefaultValue (1)]
144                 public virtual int BorderPadding
145                 {
146                         get { return ViewState.GetInt ("BorderPadding", 1); }
147                         set
148                         {
149                                 if (value < -1)
150                                         throw new ArgumentOutOfRangeException ();
151                                 ViewState ["BorderPadding"] = value;
152                         }
153                 }
154
155                 [Localizable (true)]
156                 public virtual string GeneralFailureText
157                 {
158                         get { return ViewState.GetString ("GeneralFailureText", "Your attempt to retrieve your password was not successful. Please try again."); }
159                         set { ViewState ["GeneralFailureText"] = value; }
160                 }
161
162                 [DefaultValue ("")]
163                 [UrlProperty]
164                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]       
165                 public virtual string HelpPageIconUrl
166                 {
167                         get { return ViewState.GetString ("HelpPageIconUrl", String.Empty); }
168                         set { ViewState ["HelpPageIconUrl"] = value; }
169                 }
170
171                 [DefaultValue ("")]
172                 [Localizable (true)]
173                 public virtual string HelpPageText
174                 {
175                         get { return ViewState.GetString ("HelpPageText", String.Empty); }
176                         set { ViewState ["HelpPageText"] = value; }
177                 }
178
179                 [DefaultValue ("")]
180                 [UrlProperty]
181                 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]    
182                 public virtual string HelpPageUrl
183                 {
184                         get { return ViewState.GetString ("HelpPageUrl", String.Empty); }
185                         set { ViewState ["HelpPageUrl"] = value; }
186                 }
187
188                 [NotifyParentProperty (true)]
189                 [PersistenceMode (PersistenceMode.InnerProperty)]
190                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
191                 [Themeable (false)]
192                 public MailDefinition MailDefinition {
193                         get {
194                                 if (_mailDefinition == null) {
195                                         _mailDefinition = new MailDefinition ();
196                                         if (IsTrackingViewState)
197                                                 ((IStateManager) _mailDefinition).TrackViewState ();
198                                 }
199                                 return _mailDefinition;
200                         }
201                 }
202
203                 [DefaultValue ("")]
204                 [Themeable (false)]
205                 public virtual string MembershipProvider
206                 {
207                         get { return ViewState.GetString ("MembershipProvider", String.Empty); }
208                         set { ViewState ["MembershipProvider"] = value; }
209                 }
210
211                 [Browsable (false)]
212                 [Filterable (false)]
213                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
214                 [Themeable (false)]
215                 public virtual string Question {
216                         get { return ViewState.GetString ("Question", ""); }
217                         private set { ViewState ["Question"] = value; }
218                 }
219
220                 [Localizable (true)]
221                 public virtual string QuestionFailureText
222                 {
223                         get { return ViewState.GetString ("QuestionFailureText", "Your answer could not be verified. Please try again."); }
224                         set { ViewState ["QuestionFailureText"] = value; }
225                 }
226
227                 [Localizable (true)]
228                 public virtual string QuestionInstructionText
229                 {
230                         get { return ViewState.GetString ("QuestionInstructionText", "Answer the following question to receive your password."); }
231                         set { ViewState ["QuestionInstructionText"] = value; }
232                 }
233
234                 [Localizable (true)]
235                 public virtual string QuestionLabelText
236                 {
237                         get { return ViewState.GetString ("QuestionLabelText", "Question:"); }
238                         set { ViewState ["QuestionLabelText"] = value; }
239                 }
240
241                 [Localizable (true)]
242                 public virtual string QuestionTitleText
243                 {
244                         get { return ViewState.GetString ("QuestionTitleText", "Identity Confirmation"); }
245                         set { ViewState ["QuestionTitleText"] = value; }
246                 }
247                 [DefaultValue (true)]
248                 public virtual bool RenderOuterTable {
249                         get { return renderOuterTable; }
250                         set { renderOuterTable = value; }
251                 }
252                 [DefaultValue ("")]
253                 [UrlProperty]
254                 [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]       
255                 public virtual string SubmitButtonImageUrl
256                 {
257                         get { return ViewState.GetString ("SubmitButtonImageUrl", String.Empty); }
258                         set { ViewState ["SubmitButtonImageUrl"] = value; }
259                 }
260
261                 [Localizable (true)]
262                 public virtual string SubmitButtonText
263                 {
264                         get { return ViewState.GetString ("SubmitButtonText", "Submit"); }
265                         set { ViewState ["SubmitButtonText"] = value; }
266                 }
267
268                 [DefaultValue (ButtonType.Button)]
269                 public virtual ButtonType SubmitButtonType
270                 {
271                         get
272                         {
273                                 object o = ViewState ["SubmitButtonType"];
274                                 return (o == null) ? ButtonType.Button : (ButtonType) o;
275                         }
276                         set
277                         {
278                                 if ((value < ButtonType.Button) || (value > ButtonType.Link))
279                                         throw new ArgumentOutOfRangeException ("SubmitButtonType");
280                                 ViewState ["SubmitButtonType"] = (int) value;
281                         }
282                 }
283
284                 [DefaultValue ("")]
285                 [UrlProperty]
286                 [Editor ("System.Web.UI.Design.UrlEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]    
287                 [Themeable (false)]
288                 public virtual string SuccessPageUrl
289                 {
290                         get { return ViewState.GetString ("SuccessPageUrl", String.Empty); }
291                         set { ViewState ["SuccessPageUrl"] = value; }
292                 }
293
294                 [Localizable (true)]
295                 public virtual string SuccessText
296                 {
297                         get { return ViewState.GetString ("SuccessText", "Your password has been sent to you."); }
298                         set { ViewState ["SuccessText"] = value; }
299                 }
300
301                 [DefaultValue (LoginTextLayout.TextOnLeft)]
302                 public virtual LoginTextLayout TextLayout {
303                         get
304                         {
305                                 object o = ViewState ["TextLayout"];
306                                 return (o == null) ? LoginTextLayout.TextOnLeft : (LoginTextLayout) o;
307                         }
308                         set
309                         {
310                                 if ((value < LoginTextLayout.TextOnLeft) || (value > LoginTextLayout.TextOnTop))
311                                         throw new ArgumentOutOfRangeException ("TextLayout");
312                                 ViewState ["TextLayout"] = (int) value;
313                         }
314                 }
315
316                 [DefaultValue ("")]
317                 [Localizable (true)]
318                 public virtual string UserName {
319                         get { return _username != null ? _username : String.Empty; }
320                         set { _username = value; }
321                 }
322
323                 [Localizable (true)]
324                 public virtual string UserNameFailureText
325                 {
326                         get { return ViewState.GetString ("UserNameFailureText", "We were unable to access your information. Please try again."); }
327                         set { ViewState ["UserNameFailureText"] = value; }
328                 }
329
330                 [Localizable (true)]
331                 public virtual string UserNameInstructionText
332                 {
333                         get { return ViewState.GetString ("UserNameInstructionText", "Enter your User Name to receive your password."); }
334                         set { ViewState ["UserNameInstructionText"] = value; }
335                 }
336
337                 [Localizable (true)]
338                 public virtual string UserNameLabelText
339                 {
340                         get { return ViewState.GetString ("UserNameLabelText", "User Name:"); }
341                         set { ViewState ["UserNameLabelText"] = value; }
342                 }
343
344                 [Localizable (true)]
345                 public virtual string UserNameRequiredErrorMessage
346                 {
347                         get { return ViewState.GetString ("UserNameRequiredErrorMessage", "User Name is required."); }
348                         set { ViewState ["UserNameRequiredErrorMessage"] = value; }
349                 }
350
351                 [Localizable (true)]
352                 public virtual string UserNameTitleText
353                 {
354                         get { return ViewState.GetString ("UserNameTitleText", "Forgot Your Password?"); }
355                         set { ViewState ["UserNameTitleText"] = value; }
356                 }
357
358                 [Browsable (false)]
359                 [PersistenceMode (PersistenceMode.InnerProperty)]
360                 [TemplateContainer (typeof (PasswordRecovery))]
361                 public virtual ITemplate QuestionTemplate
362                 {
363                         get { return _questionTemplate; }
364                         set { _questionTemplate = value; }
365                 }
366
367                 [Browsable (false)]
368                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
369                 public Control QuestionTemplateContainer
370                 {
371                         get {
372                                 if (_questionTemplateContainer == null) {
373                                         _questionTemplateContainer = new QuestionContainer (this);
374                                         ITemplate template = QuestionTemplate;
375                                         if (template != null)
376                                                 _questionTemplateContainer.InstantiateTemplate (template);
377                                 }
378                                 
379                                 return _questionTemplateContainer;
380                         }
381                 }
382
383                 [Browsable (false)]
384                 [PersistenceMode (PersistenceMode.InnerProperty)]
385                 [TemplateContainer (typeof (PasswordRecovery))]
386                 public virtual ITemplate SuccessTemplate
387                 {
388                         get { return _successTemplate; }
389                         set { _successTemplate = value; }
390                 }
391
392                 [Browsable (false)]
393                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394                 public Control SuccessTemplateContainer
395                 {
396                         get {
397                                 if (_successTemplateContainer == null) {
398                                         _successTemplateContainer = new SuccessContainer (this);
399                                         ITemplate template = SuccessTemplate;
400                                         if (template != null)
401                                                 _successTemplateContainer.InstantiateTemplate (template);
402                                 }
403                                 
404                                 return _successTemplateContainer;
405                         }
406                 }
407
408                 [Browsable (false)]
409                 [PersistenceMode (PersistenceMode.InnerProperty)]
410                 [TemplateContainer (typeof (PasswordRecovery))]
411                 public virtual ITemplate UserNameTemplate {
412                         get { return _userNameTemplate; }
413                         set { _userNameTemplate = value; }
414                 }
415
416                 [Browsable (false)]
417                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
418                 public Control UserNameTemplateContainer {
419                         get {
420                                 if (_userNameTemplateContainer == null) {
421                                         _userNameTemplateContainer = new UserNameContainer (this);
422                                         ITemplate template = UserNameTemplate;
423                                         if (template != null)
424                                                 _userNameTemplateContainer.InstantiateTemplate (template);
425                                 }
426                                 
427                                 return _userNameTemplateContainer;
428                         }
429                 }
430
431                 [DefaultValue (null)]
432                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
433                 [PersistenceMode (PersistenceMode.InnerProperty)]
434                 [NotifyParentProperty (true)]
435                 public TableItemStyle FailureTextStyle {
436                         get {
437                                 if (_failureTextStyle == null) {
438                                         _failureTextStyle = new TableItemStyle ();
439                                         if (IsTrackingViewState)
440                                                 _failureTextStyle.TrackViewState ();
441                                 }
442                                 return _failureTextStyle;
443                         }
444                 }
445
446                 [DefaultValue (null)]
447                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
448                 [PersistenceMode (PersistenceMode.InnerProperty)]
449                 [NotifyParentProperty (true)]
450                 public TableItemStyle HyperLinkStyle {
451                         get {
452                                 if (_hyperLinkStyle == null) {
453                                         _hyperLinkStyle = new TableItemStyle ();
454                                         if (IsTrackingViewState)
455                                                 _hyperLinkStyle.TrackViewState ();
456                                 }
457                                 return _hyperLinkStyle;
458                         }
459                 }
460
461                 [DefaultValue (null)]
462                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
463                 [PersistenceMode (PersistenceMode.InnerProperty)]
464                 [NotifyParentProperty (true)]
465                 public TableItemStyle InstructionTextStyle {
466                         get {
467                                 if (_instructionTextStyle == null) {
468                                         _instructionTextStyle = new TableItemStyle ();
469                                         if (IsTrackingViewState)
470                                                 _instructionTextStyle.TrackViewState ();
471                                 }
472                                 return _instructionTextStyle;
473                         }
474                 }
475
476                 [DefaultValue (null)]
477                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
478                 [PersistenceMode (PersistenceMode.InnerProperty)]
479                 [NotifyParentProperty (true)]
480                 public TableItemStyle LabelStyle {
481                         get {
482                                 if (_labelStyle == null) {
483                                         _labelStyle = new TableItemStyle ();
484                                         if (IsTrackingViewState)
485                                                 _labelStyle.TrackViewState ();
486                                 }
487                                 return _labelStyle;
488                         }
489                 }
490
491                 [DefaultValue (null)]
492                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
493                 [PersistenceMode (PersistenceMode.InnerProperty)]
494                 [NotifyParentProperty (true)]
495                 public Style SubmitButtonStyle {
496                         get {
497                                 if (_submitButtonStyle == null) {
498                                         _submitButtonStyle = new TableItemStyle ();
499                                         if (IsTrackingViewState)
500                                                 _submitButtonStyle.TrackViewState ();
501                                 }
502                                 return _submitButtonStyle;
503                         }
504                 }
505
506                 [DefaultValue (null)]
507                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
508                 [PersistenceMode (PersistenceMode.InnerProperty)]
509                 [NotifyParentProperty (true)]
510                 public TableItemStyle SuccessTextStyle {
511                         get {
512                                 if (_successTextStyle == null) {
513                                         _successTextStyle = new TableItemStyle ();
514                                         if (IsTrackingViewState)
515                                                 _successTextStyle.TrackViewState ();
516                                 }
517                                 return _successTextStyle;
518                         }
519                 }
520
521                 [DefaultValue (null)]
522                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
523                 [PersistenceMode (PersistenceMode.InnerProperty)]
524                 [NotifyParentProperty (true)]
525                 public Style TextBoxStyle {
526                         get {
527                                 if (_textBoxStyle == null) {
528                                         _textBoxStyle = new TableItemStyle ();
529                                         if (IsTrackingViewState)
530                                                 _textBoxStyle.TrackViewState ();
531                                 }
532                                 return _textBoxStyle;
533                         }
534                 }
535
536                 [DefaultValue (null)]
537                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
538                 [PersistenceMode (PersistenceMode.InnerProperty)]
539                 [NotifyParentProperty (true)]
540                 public TableItemStyle TitleTextStyle {
541                         get {
542                                 if (_titleTextStyle == null) {
543                                         _titleTextStyle = new TableItemStyle ();
544                                         if (IsTrackingViewState)
545                                                 _titleTextStyle.TrackViewState ();
546                                 }
547                                 return _titleTextStyle;
548                         }
549                 }
550
551                 [DefaultValue (null)]
552                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
553                 [PersistenceMode (PersistenceMode.InnerProperty)]
554                 [NotifyParentProperty (true)]
555                 public Style ValidatorTextStyle {
556                         get {
557                                 if (_validatorTextStyle == null) {
558                                         _validatorTextStyle = new TableItemStyle ();
559                                         if (IsTrackingViewState)
560                                                 _validatorTextStyle.TrackViewState ();
561                                 }
562                                 return _validatorTextStyle;
563                         }
564                 }
565
566                 #region Protected Properties
567
568                 protected override HtmlTextWriterTag TagKey {
569                         get { return HtmlTextWriterTag.Table; }
570                 }
571
572                 internal virtual MembershipProvider MembershipProviderInternal
573                 {
574                         get
575                         {
576                                 if (_provider == null)
577                                         InitMemberShipProvider ();
578
579                                 return _provider;
580                         }
581                 }
582
583                 #endregion
584
585                 protected internal override void CreateChildControls ()
586                 {
587                         ITemplate userNameTemplate = UserNameTemplate;
588                         if (userNameTemplate == null) {
589                                 userNameTemplate = new UserNameDefaultTemplate (this);
590                                 ((UserNameContainer) UserNameTemplateContainer).InstantiateTemplate (userNameTemplate);
591                         }
592                         
593                         ITemplate questionTemplate = QuestionTemplate;
594                         if (questionTemplate == null) {
595                                 questionTemplate = new QuestionDefaultTemplate (this);
596                                 ((QuestionContainer) QuestionTemplateContainer).InstantiateTemplate (questionTemplate);
597                         }
598
599                         ITemplate successTemplate = SuccessTemplate;
600                         if (successTemplate == null) {
601                                 successTemplate = new SuccessDefaultTemplate (this);
602                                 ((SuccessContainer) SuccessTemplateContainer).InstantiateTemplate (successTemplate);
603                         }
604
605                         Controls.AddAt (0, UserNameTemplateContainer);
606                         Controls.AddAt (1, QuestionTemplateContainer);
607                         Controls.AddAt (2, SuccessTemplateContainer);
608
609                         IEditableTextControl editable;
610
611                         editable = ((UserNameContainer) UserNameTemplateContainer).UserNameTextBox;
612                         if (editable != null)
613                                 editable.TextChanged += new EventHandler (UserName_TextChanged);
614
615                         editable = ((QuestionContainer) QuestionTemplateContainer).AnswerTextBox;
616                         if (editable != null)
617                                 editable.TextChanged += new EventHandler (Answer_TextChanged);
618                 }
619
620                 #region Protected methods
621
622                 protected internal override void Render (HtmlTextWriter writer)
623                 {
624                         ((QuestionContainer) QuestionTemplateContainer).UpdateChildControls ();
625
626                         for (int i = 0; i < Controls.Count; i++)
627                                 if (Controls [i].Visible)
628                                         Controls [i].Render (writer);
629                 }
630
631                 protected internal override void LoadControlState (object savedState)
632                 {
633                         if (savedState == null) return;
634                         object [] state = (object []) savedState;
635                         base.LoadControlState (state [0]);
636
637                         _currentStep = (PasswordReciveryStep) state [1];
638                         _username = (string) state [2];
639                 }
640
641                 protected internal override object SaveControlState ()
642                 {
643                         object state = base.SaveControlState ();
644                         return new object [] { state, _currentStep, _username };
645                 }
646
647                 protected override void TrackViewState ()
648                 {
649                         base.TrackViewState ();
650
651                         if (_failureTextStyle != null)
652                                 _failureTextStyle.TrackViewState ();
653
654                         if (_hyperLinkStyle != null)
655                                 _hyperLinkStyle.TrackViewState ();
656
657                         if (_instructionTextStyle != null)
658                                 _instructionTextStyle.TrackViewState ();
659
660                         if (_labelStyle != null)
661                                 _labelStyle.TrackViewState ();
662
663                         if (_submitButtonStyle != null)
664                                 _submitButtonStyle.TrackViewState ();
665
666                         if (_successTextStyle != null)
667                                 _successTextStyle.TrackViewState ();
668
669                         if (_textBoxStyle != null)
670                                 _textBoxStyle.TrackViewState ();
671
672                         if (_titleTextStyle != null)
673                                 _titleTextStyle.TrackViewState ();
674
675                         if (_validatorTextStyle != null)
676                                 _validatorTextStyle.TrackViewState ();
677
678                         if (_mailDefinition != null)
679                                 ((IStateManager) _mailDefinition).TrackViewState ();
680                 }
681
682                 protected override void LoadViewState (object savedState)
683                 {
684                         if (savedState == null)
685                                 return;
686
687                         object [] states = (object []) savedState;
688                         base.LoadViewState (states [0]);
689
690                         if (states [1] != null)
691                                 FailureTextStyle.LoadViewState (states [1]);
692
693                         if (states [2] != null)
694                                 HyperLinkStyle.LoadViewState (states [2]);
695
696                         if (states [3] != null)
697                                 InstructionTextStyle.LoadViewState (states [3]);
698
699                         if (states [4] != null)
700                                 LabelStyle.LoadViewState (states [4]);
701
702                         if (states [5] != null)
703                                 SubmitButtonStyle.LoadViewState (states [5]);
704
705                         if (states [6] != null)
706                                 SuccessTextStyle.LoadViewState (states [6]);
707
708                         if (states [7] != null)
709                                 TextBoxStyle.LoadViewState (states [7]);
710
711                         if (states [8] != null)
712                                 TitleTextStyle.LoadViewState (states [8]);
713
714                         if (states [9] != null)
715                                 ValidatorTextStyle.LoadViewState (states [9]);
716
717                         if (states [10] != null)
718                                 ((IStateManager) MailDefinition).LoadViewState (states [10]);
719                 }
720
721                 protected override object SaveViewState ()
722                 {
723                         object [] states = new object [11];
724                         states [0] = base.SaveViewState ();
725
726                         if (_failureTextStyle != null)
727                                 states [1] = _failureTextStyle.SaveViewState ();
728
729                         if (_hyperLinkStyle != null)
730                                 states [2] = _hyperLinkStyle.SaveViewState ();
731
732                         if (_instructionTextStyle != null)
733                                 states [3] = _instructionTextStyle.SaveViewState ();
734
735                         if (_labelStyle != null)
736                                 states [4] = _labelStyle.SaveViewState ();
737
738                         if (_submitButtonStyle != null)
739                                 states [5] = _submitButtonStyle.SaveViewState ();
740
741                         if (_successTextStyle != null)
742                                 states [6] = _successTextStyle.SaveViewState ();
743
744                         if (_textBoxStyle != null)
745                                 states [7] = _textBoxStyle.SaveViewState ();
746
747                         if (_titleTextStyle != null)
748                                 states [8] = _titleTextStyle.SaveViewState ();
749
750                         if (_validatorTextStyle != null)
751                                 states [9] = _validatorTextStyle.SaveViewState ();
752
753                         if (_mailDefinition != null)
754                                 states [10] = ((IStateManager) _mailDefinition).SaveViewState ();
755
756                         for (int i = 0; i < states.Length; i++) {
757                                 if (states [i] != null)
758                                         return states;
759                         }
760                         return null;
761
762                 }
763
764                 #endregion
765
766                 void ProcessCommand (CommandEventArgs args)
767                 {
768                         if (!Page.IsValid)
769                                 return;
770
771                         switch (_currentStep) {
772                                 case PasswordReciveryStep.StepUserName:
773                                         ProcessUserName ();
774                                         break;
775                                 case PasswordReciveryStep.StepAnswer:
776                                         ProcessUserAnswer ();
777                                         break;
778                         }
779
780                 }
781
782                 void ProcessUserName ()
783                 {
784                         LoginCancelEventArgs args = new LoginCancelEventArgs ();
785                         OnVerifyingUser (args);
786                         if (args.Cancel)
787                                 return;
788
789                         MembershipUser user = MembershipProviderInternal.GetUser (UserName, false);
790                         if (user == null) {
791                                 OnUserLookupError (EventArgs.Empty);
792                                 ((UserNameContainer) UserNameTemplateContainer).FailureTextLiteral.Text = UserNameFailureText;
793                                 return;
794                         }
795
796                         if (!MembershipProviderInternal.RequiresQuestionAndAnswer) {
797                                 GenerateAndSendEmail ();
798
799                                 _currentStep = PasswordReciveryStep.StepSuccess;
800                                 return;
801                         }
802
803                         Question = user.PasswordQuestion;
804                         _currentStep = PasswordReciveryStep.StepAnswer;
805                         return;
806                 }
807
808                 void ProcessUserAnswer ()
809                 {
810                         LoginCancelEventArgs args = new LoginCancelEventArgs ();
811                         OnVerifyingAnswer (args);
812                         if (args.Cancel)
813                                 return;
814
815                         MembershipUser user = MembershipProviderInternal.GetUser (UserName, false);
816                         if (user == null || string.IsNullOrEmpty (user.Email)) {
817                                 ((QuestionContainer) QuestionTemplateContainer).FailureTextLiteral.Text = GeneralFailureText;
818                                 return;
819                         }
820
821                         GenerateAndSendEmail ();
822
823                         _currentStep = PasswordReciveryStep.StepSuccess;
824                         return;
825                 }
826
827                 void GenerateAndSendEmail ()
828                 {
829                         string newPassword = "";
830                         try {
831                                 if (MembershipProviderInternal.EnablePasswordRetrieval) {
832                                         newPassword = MembershipProviderInternal.GetPassword (UserName, Answer);
833                                 }
834                                 else if (MembershipProviderInternal.EnablePasswordReset) {
835                                         newPassword = MembershipProviderInternal.ResetPassword (UserName, Answer);
836                                 }
837                                 else
838                                         throw new HttpException ("Membership provider does not support password retrieval or reset.");
839                         }
840                         catch (MembershipPasswordException) {
841                                 OnAnswerLookupError (EventArgs.Empty);
842                                 ((QuestionContainer) QuestionTemplateContainer).FailureTextLiteral.Text = QuestionFailureText;
843                                 return;
844                         }
845
846                         SendPasswordByMail (UserName, newPassword);
847                 }
848
849                 void InitMemberShipProvider ()
850                 {
851                         string mp = MembershipProvider;
852                         _provider = (mp.Length == 0) ? _provider = Membership.Provider : Membership.Providers [mp];
853                         if (_provider == null)
854                                 throw new HttpException (Locale.GetText ("No provider named '{0}' could be found.", mp));
855                 }
856
857                 void SendPasswordByMail (string username, string password)
858                 {
859                         MembershipUser user = MembershipProviderInternal.GetUser (UserName, false);
860                         if (user == null)
861                                 return;
862
863                         // DO NOT change format of the message - it has to be exactly the same as in
864                         // .NET as some software (e.g. YetAnotherForum) depends on it.
865                         string messageText = "Please return to the site and log in using the following information.\n" +
866                                 "User Name: <%USERNAME%>\nPassword: <%PASSWORD%>\n";
867
868                         ListDictionary dictionary = new ListDictionary (StringComparer.OrdinalIgnoreCase);
869                         dictionary.Add ("<%USERNAME%>", username);
870                         dictionary.Add ("<% UserName %>", username);
871                         dictionary.Add ("<%PASSWORD%>", password);
872                         dictionary.Add ("<% Password %>", password);
873
874                         MailMessage message = null;
875                         
876                         if (MailDefinition.BodyFileName.Length == 0)
877                                 message = MailDefinition.CreateMailMessage (user.Email, dictionary, messageText, this);
878                         else
879                                 message = MailDefinition.CreateMailMessage (user.Email, dictionary, this);
880
881                         if (string.IsNullOrEmpty (message.Subject))
882                                 message.Subject = "Password";
883
884                         MailMessageEventArgs args = new MailMessageEventArgs (message);
885                         OnSendingMail (args);
886
887                         SmtpClient smtpClient = new SmtpClient ();
888                         try {
889                                 smtpClient.Send (message);
890                         }
891                         catch (Exception e) {
892                                 SendMailErrorEventArgs mailArgs = new SendMailErrorEventArgs (e);
893                                 OnSendMailError (mailArgs);
894                                 if (!mailArgs.Handled)
895                                         throw e;
896                         }
897                 }
898
899                 #region Event handlers
900
901                 protected virtual void OnAnswerLookupError (EventArgs e)
902                 {
903                 }
904
905                 protected override bool OnBubbleEvent (object source, EventArgs e)
906                 {
907                         CommandEventArgs args = e as CommandEventArgs;
908                         if (e != null && args.CommandName == SubmitButtonCommandName) {
909                                 ProcessCommand (args);
910                                 return true;
911                         }
912                         return base.OnBubbleEvent (source, e);
913                 }
914
915                 protected internal override void OnInit (EventArgs e)
916                 {
917                         Page.RegisterRequiresControlState (this);
918                         base.OnInit (e);
919                 }
920
921                 protected internal override void OnPreRender (EventArgs e)
922                 {
923                         UserNameTemplateContainer.Visible = false;
924                         QuestionTemplateContainer.Visible = false;
925                         SuccessTemplateContainer.Visible = false;
926
927                         switch (_currentStep) {
928                                 case PasswordReciveryStep.StepUserName:
929                                         UserNameTemplateContainer.Visible = true;
930                                         break;
931                                 case PasswordReciveryStep.StepAnswer:
932                                         QuestionTemplateContainer.Visible = true;
933                                         break;
934                                 case PasswordReciveryStep.StepSuccess:
935                                         SuccessTemplateContainer.Visible = true;
936                                         break;
937                         }
938
939                         base.OnPreRender (e);
940                 }
941
942                 protected virtual void OnSendingMail (MailMessageEventArgs e)
943                 {
944                         MailMessageEventHandler eh = events [sendingMailEvent] as MailMessageEventHandler;
945                         if (eh != null)
946                                 eh (this, e);
947                 }
948
949                 protected virtual void OnSendMailError (SendMailErrorEventArgs e)
950                 {
951                         SendMailErrorEventHandler eh = events [sendingMailEvent] as SendMailErrorEventHandler;
952                         if (eh != null)
953                                 eh (this, e);
954                 }
955
956                 protected virtual void OnUserLookupError (EventArgs e)
957                 {
958                         EventHandler eh = events [userLookupErrorEvent] as EventHandler;
959                         if (eh != null)
960                                 eh (this, e);
961                 }
962
963                 protected virtual void OnVerifyingAnswer (LoginCancelEventArgs e)
964                 {
965                         LoginCancelEventHandler eh = events [verifyingAnswerEvent] as LoginCancelEventHandler;
966                         if (eh != null)
967                                 eh (this, e);
968                 }
969
970                 protected virtual void OnVerifyingUser (LoginCancelEventArgs e)
971                 {
972                         LoginCancelEventHandler eh = events [verifyingUserEvent] as LoginCancelEventHandler;
973                         if (eh != null)
974                                 eh (this, e);
975                 }
976
977                 #endregion
978
979                 #region Private Event Handlers
980
981                 void UserName_TextChanged (object sender, EventArgs e)
982                 {
983                         UserName = ((ITextControl) sender).Text;
984                 }
985
986                 void Answer_TextChanged (object sender, EventArgs e)
987                 {
988                         _answer = ((ITextControl) sender).Text;
989                 }
990
991                 #endregion
992
993                 [MonoTODO ("Not implemented")]
994                 protected override void SetDesignModeState (IDictionary data)
995                 {
996                         throw new NotImplementedException ();
997                 }
998
999                 // TODO: merge with BaseCheckPasswordContainer
1000                 abstract class BasePasswordRecoveryContainer : Control, INamingContainer
1001                 {
1002                         protected readonly PasswordRecovery _owner = null;
1003                         bool renderOuterTable;
1004                         Table _table;
1005                         TableCell _containerCell = null;
1006
1007                         public BasePasswordRecoveryContainer (PasswordRecovery owner)
1008                         {
1009                                 _owner = owner;
1010                                 renderOuterTable = _owner.RenderOuterTable;
1011                                 if (renderOuterTable)
1012                                         InitTable ();
1013                         }
1014
1015                         public void InstantiateTemplate (ITemplate template)
1016                         {
1017                                 if (!renderOuterTable)
1018                                         template.InstantiateIn (this);
1019                                 else
1020                                         template.InstantiateIn (_containerCell);
1021                         }
1022
1023                         void InitTable ()
1024                         {
1025                                 _table = new Table ();
1026                                 string id = _owner.ID;
1027                                 if (!String.IsNullOrEmpty (id))
1028                                         _table.Attributes.Add ("id", id);
1029
1030                                 _table.CellSpacing = 0;
1031                                 _table.CellPadding = _owner.BorderPadding;
1032
1033                                 _containerCell = new TableCell ();
1034
1035                                 TableRow row = new TableRow ();
1036                                 row.Cells.Add (_containerCell);
1037                                 _table.Rows.Add (row);
1038
1039                                 Controls.AddAt (0, _table);
1040                         }
1041
1042                         protected internal override void OnPreRender (EventArgs e)
1043                         {
1044                                 if (_table != null)
1045                                         _table.ApplyStyle (_owner.ControlStyle);
1046                                 base.OnPreRender (e);
1047                         }
1048
1049                         public abstract void UpdateChildControls();
1050                 }
1051
1052
1053                 sealed class QuestionContainer : BasePasswordRecoveryContainer
1054                 {
1055                         public QuestionContainer (PasswordRecovery owner)
1056                                 : base (owner)
1057                         {
1058                         }
1059                         // Requried controls
1060                         public IEditableTextControl AnswerTextBox
1061                         {
1062                                 get
1063                                 {
1064                                         Control c = FindControl ("Answer");
1065                                         if (c == null)
1066                                                 throw new HttpException ("QuestionTemplate does not contain an IEditableTextControl with ID Answer for the username.");
1067                                         return c as IEditableTextControl;
1068                                 }
1069                         }
1070                         // Optional controls
1071                         public Literal UserNameLiteral
1072                         {
1073                                 get { return FindControl ("UserName") as Literal; }
1074                         }
1075                         public Literal QuestionLiteral
1076                         {
1077                                 get { return FindControl ("Question") as Literal; }
1078                         }
1079                         public Literal FailureTextLiteral
1080                         {
1081                                 get { return FindControl ("FailureText") as Literal; }
1082                         }
1083
1084                         public override void UpdateChildControls ()
1085                         {
1086                                 if (UserNameLiteral != null)
1087                                         UserNameLiteral.Text = _owner.UserName;
1088
1089                                 if (QuestionLiteral != null)
1090                                         QuestionLiteral.Text = _owner.Question;
1091                         }
1092                 }
1093
1094                 sealed class SuccessContainer : BasePasswordRecoveryContainer
1095                 {
1096                         public SuccessContainer (PasswordRecovery owner)
1097                                 : base (owner)
1098                         {
1099                         }
1100
1101                         public override void UpdateChildControls ()
1102                         {
1103                         }
1104                 }
1105
1106                 sealed class UserNameContainer : BasePasswordRecoveryContainer
1107                 {
1108                         public UserNameContainer (PasswordRecovery owner)
1109                                 : base (owner)
1110                         {
1111                         }
1112                         // Requried controls
1113                         public IEditableTextControl UserNameTextBox
1114                         {
1115                                 get
1116                                 {
1117                                         Control c = FindControl ("UserName");
1118                                         if (c == null)
1119                                                 throw new HttpException ("UserNameTemplate does not contain an IEditableTextControl with ID UserName for the username.");
1120                                         return c as IEditableTextControl;
1121                                 }
1122                         }
1123                         // Optional controls
1124                         public ITextControl FailureTextLiteral
1125                         {
1126                                 get { return FindControl ("FailureText") as ITextControl; }
1127                         }
1128
1129                         public override void UpdateChildControls ()
1130                         {
1131                         }
1132                 }
1133
1134                 class TemplateUtils
1135                 {
1136                         public static TableRow CreateRow(Control c1, Control c2, Style s1, Style s2, bool twoCells)
1137                         {
1138                                 TableRow row = new TableRow ();
1139                                 TableCell cell1 = new TableCell ();
1140
1141                                 cell1.Controls.Add (c1);
1142                                 if (s1 != null)
1143                                         cell1.ApplyStyle (s1);
1144
1145                                 row.Cells.Add (cell1);
1146
1147                                 if (c2 != null) {
1148                                         TableCell cell2 = new TableCell ();
1149                                         cell2.Controls.Add (c2);
1150
1151                                         if (s2 != null)
1152                                                 cell2.ApplyStyle (s2);
1153
1154                                         row.Cells.Add (cell2);
1155
1156                                         cell1.HorizontalAlign = HorizontalAlign.Right;
1157                                         cell2.HorizontalAlign = HorizontalAlign.Left;
1158                                 }
1159                                 else {
1160                                         cell1.HorizontalAlign = HorizontalAlign.Center;
1161                                         if (twoCells)
1162                                                 cell1.ColumnSpan = 2;
1163                                 }
1164                                 
1165                                 return row;
1166                         }
1167
1168                         public static TableRow CreateHelpRow (string pageUrl, string linkText, string linkIcon, Style linkStyle, bool twoCells)
1169                         {
1170                                 TableRow row = new TableRow ();
1171                                 TableCell cell1 = new TableCell ();
1172
1173                                 if (linkIcon.Length > 0) {
1174                                         Image img = new Image ();
1175                                         img.ImageUrl = linkIcon;
1176                                         cell1.Controls.Add (img);
1177                                 }
1178                                 if (linkText.Length > 0) {
1179                                         HyperLink link = new HyperLink ();
1180                                         link.NavigateUrl = pageUrl;
1181                                         link.Text = linkText;
1182                                         link.ControlStyle.CopyTextStylesFrom (linkStyle);
1183                                         cell1.Controls.Add (link);
1184                                 }
1185
1186                                 if (twoCells)
1187                                         cell1.ColumnSpan = 2;
1188
1189                                 row.ControlStyle.CopyFrom (linkStyle);
1190                                 row.Cells.Add (cell1);
1191                                 return row;
1192                         }
1193                 }
1194
1195                 sealed class UserNameDefaultTemplate : ITemplate
1196                 {
1197                         readonly PasswordRecovery _owner = null;
1198
1199                         public UserNameDefaultTemplate (PasswordRecovery _owner)
1200                         {
1201                                 this._owner = _owner;
1202                         }
1203
1204                         public void InstantiateIn (Control container)
1205                         {
1206                                 Table table = new Table ();
1207                                 table.CellPadding = 0;
1208
1209                                 bool twoCells = _owner.TextLayout == LoginTextLayout.TextOnLeft;
1210
1211                                 // row 0
1212                                 table.Rows.Add (
1213                                         TemplateUtils.CreateRow (new LiteralControl (_owner.UserNameTitleText), null, _owner.TitleTextStyle, null, twoCells));
1214
1215                                 // row 1
1216                                 table.Rows.Add (
1217                                         TemplateUtils.CreateRow (new LiteralControl (_owner.UserNameInstructionText), null, _owner.InstructionTextStyle, null, twoCells));
1218
1219                                 // row 2
1220                                 TextBox UserNameTextBox = new TextBox ();
1221                                 UserNameTextBox.ID = "UserName";
1222                                 UserNameTextBox.Text = _owner.UserName;
1223                                 UserNameTextBox.ApplyStyle (_owner.TextBoxStyle);
1224
1225                                 Label UserNameLabel = new Label ();
1226                                 UserNameLabel.ID = "UserNameLabel";
1227                                 UserNameLabel.AssociatedControlID = "UserName";
1228                                 UserNameLabel.Text = _owner.UserNameLabelText;
1229                                 UserNameLabel.ApplyStyle (_owner.LabelStyle);
1230
1231                                 RequiredFieldValidator UserNameRequired = new RequiredFieldValidator ();
1232                                 UserNameRequired.ID = "UserNameRequired";
1233                                 UserNameRequired.ControlToValidate = "UserName";
1234                                 UserNameRequired.ErrorMessage = _owner.UserNameRequiredErrorMessage;
1235                                 UserNameRequired.ToolTip = _owner.UserNameRequiredErrorMessage;
1236                                 UserNameRequired.Text = "*";
1237                                 UserNameRequired.ValidationGroup = _owner.ID;
1238                                 UserNameRequired.ApplyStyle (_owner.ValidatorTextStyle);
1239
1240                                 if (twoCells) {
1241                                         TableRow row = TemplateUtils.CreateRow (UserNameLabel, UserNameTextBox, null, null, twoCells);
1242                                         row.Cells [1].Controls.Add (UserNameRequired);
1243                                         table.Rows.Add (row);
1244                                 }
1245                                 else {
1246                                         table.Rows.Add (TemplateUtils.CreateRow (UserNameLabel, null, null, null, twoCells));
1247                                         TableRow row = TemplateUtils.CreateRow (UserNameTextBox, null, null, null, twoCells);
1248                                         row.Cells [0].Controls.Add (UserNameRequired);
1249                                         table.Rows.Add (row);
1250                                 }
1251
1252                                 // row 3
1253                                 Literal FailureText = new Literal ();
1254                                 FailureText.ID = "FailureText";
1255                                 if (_owner.FailureTextStyle.ForeColor.IsEmpty)
1256                                         _owner.FailureTextStyle.ForeColor = System.Drawing.Color.Red;
1257                                 table.Rows.Add (TemplateUtils.CreateRow (FailureText, null, _owner.FailureTextStyle, null, twoCells));
1258
1259                                 // row 4
1260                                 WebControl SubmitButton = null;
1261                                 switch (_owner.SubmitButtonType) {
1262                                         case ButtonType.Button:
1263                                                 SubmitButton = new Button ();
1264                                                 break;
1265                                         case ButtonType.Image:
1266                                                 SubmitButton = new ImageButton ();
1267                                                 break;
1268                                         case ButtonType.Link:
1269                                                 SubmitButton = new LinkButton ();
1270                                                 break;
1271                                 }
1272
1273                                 SubmitButton.ID = "SubmitButton";
1274                                 SubmitButton.ApplyStyle (_owner.SubmitButtonStyle);
1275                                 ((IButtonControl) SubmitButton).CommandName = PasswordRecovery.SubmitButtonCommandName;
1276                                 ((IButtonControl) SubmitButton).Text = _owner.SubmitButtonText;
1277                                 ((IButtonControl) SubmitButton).ValidationGroup = _owner.ID;
1278
1279                                 TableRow buttonRow = TemplateUtils.CreateRow (SubmitButton, null, null, null, twoCells);
1280                                 buttonRow.Cells [0].HorizontalAlign = HorizontalAlign.Right;
1281                                 table.Rows.Add (buttonRow);
1282
1283                                 // row 5
1284                                 table.Rows.Add (
1285                                         TemplateUtils.CreateHelpRow (
1286                                         _owner.HelpPageUrl, _owner.HelpPageText, _owner.HelpPageIconUrl, _owner.HyperLinkStyle, twoCells));
1287
1288                                 container.Controls.Add (table);
1289                         }
1290                 }
1291
1292                 sealed class QuestionDefaultTemplate : ITemplate
1293                 {
1294                         readonly PasswordRecovery _owner = null;
1295
1296                         public QuestionDefaultTemplate (PasswordRecovery _owner)
1297                         {
1298                                 this._owner = _owner;
1299                         }
1300
1301                         public void InstantiateIn (Control container)
1302                         {
1303                                 Table table = new Table ();
1304                                 table.CellPadding = 0;
1305
1306                                 bool twoCells = _owner.TextLayout == LoginTextLayout.TextOnLeft;
1307
1308                                 // row 0
1309                                 table.Rows.Add (
1310                                         TemplateUtils.CreateRow (new LiteralControl (_owner.QuestionTitleText), null, _owner.TitleTextStyle, null, twoCells));
1311
1312                                 // row 1
1313                                 table.Rows.Add (
1314                                         TemplateUtils.CreateRow (new LiteralControl (_owner.QuestionInstructionText), null, _owner.InstructionTextStyle, null, twoCells));
1315
1316                                 // row 2
1317                                 Literal UserNameLiteral = new Literal ();
1318                                 UserNameLiteral.ID = "UserName";
1319
1320                                 table.Rows.Add (
1321                                         TemplateUtils.CreateRow (new LiteralControl (_owner.UserNameLabelText), UserNameLiteral, _owner.LabelStyle, _owner.LabelStyle, twoCells));
1322
1323                                 // row 3
1324                                 Literal QuestionLiteral = new Literal ();
1325                                 QuestionLiteral.ID = "Question";
1326
1327                                 table.Rows.Add (
1328                                         TemplateUtils.CreateRow (new LiteralControl (_owner.QuestionLabelText), QuestionLiteral, _owner.LabelStyle, _owner.LabelStyle, twoCells));
1329
1330                                 // row 5
1331                                 TextBox AnswerTextBox = new TextBox ();
1332                                 AnswerTextBox.ID = "Answer";
1333                                 AnswerTextBox.ApplyStyle (_owner.TextBoxStyle);
1334
1335                                 Label AnswerLabel = new Label ();
1336                                 AnswerLabel.ID = "AnswerLabel";
1337                                 AnswerLabel.AssociatedControlID = "Answer";
1338                                 AnswerLabel.Text = _owner.AnswerLabelText;
1339                                 AnswerLabel.ApplyStyle (_owner.LabelStyle);
1340
1341                                 RequiredFieldValidator AnswerRequired = new RequiredFieldValidator ();
1342                                 AnswerRequired.ID = "AnswerRequired";
1343                                 AnswerRequired.ControlToValidate = "Answer";
1344                                 AnswerRequired.ErrorMessage = _owner.AnswerRequiredErrorMessage;
1345                                 AnswerRequired.ToolTip = _owner.AnswerRequiredErrorMessage;
1346                                 AnswerRequired.Text = "*";
1347                                 AnswerRequired.ValidationGroup = _owner.ID;
1348                                 AnswerRequired.ApplyStyle (_owner.ValidatorTextStyle);
1349
1350                                 if (twoCells) {
1351                                         TableRow row = TemplateUtils.CreateRow (AnswerLabel, AnswerTextBox, null, null, twoCells);
1352                                         row.Cells [1].Controls.Add (AnswerRequired);
1353                                         table.Rows.Add (row);
1354                                 }
1355                                 else {
1356                                         table.Rows.Add (TemplateUtils.CreateRow (AnswerLabel, null, null, null, twoCells));
1357                                         TableRow row = TemplateUtils.CreateRow (AnswerTextBox, null, null, null, twoCells);
1358                                         row.Cells [0].Controls.Add (AnswerRequired);
1359                                         table.Rows.Add (row);
1360                                 }
1361
1362                                 // row 6
1363                                 Literal FailureText = new Literal ();
1364                                 FailureText.ID = "FailureText";
1365                                 if (_owner.FailureTextStyle.ForeColor.IsEmpty)
1366                                         _owner.FailureTextStyle.ForeColor = System.Drawing.Color.Red;
1367                                 table.Rows.Add (TemplateUtils.CreateRow (FailureText, null, _owner.FailureTextStyle, null, twoCells));
1368
1369                                 // row 7
1370                                 WebControl SubmitButton = null;
1371                                 switch (_owner.SubmitButtonType) {
1372                                         case ButtonType.Button:
1373                                                 SubmitButton = new Button ();
1374                                                 break;
1375                                         case ButtonType.Image:
1376                                                 SubmitButton = new ImageButton ();
1377                                                 break;
1378                                         case ButtonType.Link:
1379                                                 SubmitButton = new LinkButton ();
1380                                                 break;
1381                                 }
1382
1383                                 SubmitButton.ID = "SubmitButton";
1384                                 SubmitButton.ApplyStyle (_owner.SubmitButtonStyle);
1385                                 ((IButtonControl) SubmitButton).CommandName = PasswordRecovery.SubmitButtonCommandName;
1386                                 ((IButtonControl) SubmitButton).Text = _owner.SubmitButtonText;
1387                                 ((IButtonControl) SubmitButton).ValidationGroup = _owner.ID;
1388
1389                                 TableRow buttonRow = TemplateUtils.CreateRow (SubmitButton, null, null, null, twoCells);
1390                                 buttonRow.Cells [0].HorizontalAlign = HorizontalAlign.Right;
1391                                 table.Rows.Add (buttonRow);
1392
1393                                 // row 8
1394                                 table.Rows.Add (
1395                                         TemplateUtils.CreateHelpRow (
1396                                         _owner.HelpPageUrl, _owner.HelpPageText, _owner.HelpPageIconUrl, _owner.HyperLinkStyle, twoCells));
1397
1398                                 container.Controls.Add (table);
1399                         }
1400                 }
1401
1402                 sealed class SuccessDefaultTemplate : ITemplate
1403                 {
1404                         readonly PasswordRecovery _owner = null;
1405
1406                         public SuccessDefaultTemplate (PasswordRecovery _owner)
1407                         {
1408                                 this._owner = _owner;
1409                         }
1410
1411                         public void InstantiateIn (Control container)
1412                         {
1413                                 Table table = new Table ();
1414                                 table.CellPadding = 0;
1415
1416                                 bool twoCells = _owner.TextLayout == LoginTextLayout.TextOnLeft;
1417
1418                                 // row 0
1419                                 table.Rows.Add (
1420                                         TemplateUtils.CreateRow (new LiteralControl (_owner.SuccessText), null, _owner.SuccessTextStyle, null, twoCells));
1421
1422                                 container.Controls.Add (table);
1423                         }
1424                 }
1425
1426                 enum PasswordReciveryStep
1427                 {
1428                         StepUserName,
1429                         StepAnswer,
1430                         StepSuccess,
1431                 }
1432         }
1433 }
1434