Moved chain building and validation from Mono.Security to System
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / WebControl.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    (pbartok@novell.com)
24 //
25 //
26
27 using System.ComponentModel;
28 using System.Drawing;
29 using System.Security.Permissions;
30
31 namespace System.Web.UI.WebControls {
32
33         // CAS
34         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
35         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
36         // attributes
37         [ParseChildren (true)]
38 #if NET_2_0
39         [PersistChildrenAttribute (false, false)]
40         [Themeable (true)]
41 #else   
42         [PersistChildrenAttribute (false)]
43 #endif          
44         public class WebControl : Control, IAttributeAccessor {
45                 Style style;
46                 HtmlTextWriterTag tag;
47                 string tag_name;
48                 AttributeCollection attributes;
49                 StateBag attribute_state;
50                 bool enabled;
51                 bool track_enabled_state;
52
53                 public WebControl (HtmlTextWriterTag tag) 
54                 {
55                         this.tag = tag;
56                         this.enabled = true;
57                 }
58
59                 protected WebControl () : this (HtmlTextWriterTag.Span) 
60                 {
61                 }
62
63                 protected WebControl (string tag) 
64                 {
65                         this.tag = HtmlTextWriterTag.Unknown;
66                         this.tag_name = tag;
67                         this.enabled = true;
68                 }
69
70 #if ONLY_1_1
71                 [Bindable(true)]
72 #endif          
73                 [DefaultValue("")]
74                 [WebSysDescription ("")]
75                 [WebCategory ("Behavior")]
76                 public virtual string AccessKey {
77                         get {
78                                 return ViewState.GetString ("AccessKey", string.Empty);
79                         }
80                         set {
81                                 if (value == null || value.Length < 2)
82                                         ViewState ["AccessKey"] = value;
83                                 else
84                                         throw new ArgumentException ("AccessKey can only be null, empty or a single character", "value");
85                         }
86                 }
87
88                 [Browsable(false)]
89                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
90                 [WebSysDescription ("")]
91                 [WebCategory ("Behavior")]
92                 public AttributeCollection Attributes {
93                         get {
94                                 if (attributes == null) {
95                                         attribute_state = new StateBag (true);
96                                         if (IsTrackingViewState)
97                                                 attribute_state.TrackViewState ();
98                                         
99                                         attributes = new AttributeCollection (attribute_state);
100                                 }
101                                 return attributes;
102                         }
103                 }
104
105 #if ONLY_1_1
106                 [Bindable(true)]
107 #endif          
108                 [DefaultValue(typeof (Color), "")]
109                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
110                 [WebSysDescription ("")]
111                 [WebCategory ("Appearance")]
112                 public virtual Color BackColor {
113                         get {
114                                 if (style == null) 
115                                         return Color.Empty;
116                                 
117                                 return style.BackColor;
118                         }
119                         set {
120                                 ControlStyle.BackColor = value;
121                         }
122                 }
123
124 #if ONLY_1_1
125                 [Bindable(true)]
126 #endif          
127                 [DefaultValue(typeof (Color), "")]
128                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
129                 [WebSysDescription ("")]
130                 [WebCategory ("Appearance")]
131                 public virtual Color BorderColor {
132                         get {
133                                 if (style == null) 
134                                         return Color.Empty;
135
136                                 return style.BorderColor;
137                         }
138
139                         set {
140                                 ControlStyle.BorderColor = value;
141                         }
142                 }
143
144 #if ONLY_1_1
145                 [Bindable(true)]
146 #endif          
147                 [DefaultValue(BorderStyle.NotSet)]
148                 [WebSysDescription ("")]
149                 [WebCategory ("Appearance")]
150                 public virtual BorderStyle BorderStyle {
151                         get {
152                                 if (style == null) 
153                                         return BorderStyle.NotSet;
154                                 
155                                 return style.BorderStyle;
156                         }
157                         set {
158                                 if (value < BorderStyle.NotSet || value > BorderStyle.Outset)
159                                         throw new ArgumentOutOfRangeException ("value");
160
161                                 ControlStyle.BorderStyle = value;
162                         }
163                 }
164
165 #if ONLY_1_1
166                 [Bindable(true)]
167 #endif          
168                 [DefaultValue(typeof (Unit), "")]
169                 [WebSysDescription ("")]
170                 [WebCategory ("Appearance")]
171                 public virtual Unit BorderWidth {
172                         get {
173                                 if (style == null) 
174                                         return Unit.Empty;
175
176                                 return style.BorderWidth;
177                         }
178                         set {
179                                 ControlStyle.BorderWidth = value;
180                         }
181                 }
182
183                 [Browsable(false)]
184                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
185                 [WebSysDescription ("")]
186                 [WebCategory ("Appearance")]
187                 public Style ControlStyle {
188                         get {
189                                 if (style == null) {
190                                         style = this.CreateControlStyle ();
191
192                                         if (IsTrackingViewState)
193                                                 style.TrackViewState ();
194                                 }
195
196                                 return style;
197                         }
198                 }
199
200                 [Browsable(false)]
201                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
202 #if NET_2_0
203                 [EditorBrowsable (EditorBrowsableState.Never)]
204 #endif
205                 public bool ControlStyleCreated {
206                         get {
207                                 return style != null;
208                         }
209                 }
210
211 #if ONLY_1_1
212                 [Bindable(true)]
213 #endif          
214                 [DefaultValue("")]
215                 [WebSysDescription ("")]
216                 [WebCategory ("Appearance")]
217                 public virtual string CssClass {
218                         get {
219                                 if (style == null) 
220                                         return string.Empty;
221                                 
222                                 return style.CssClass;
223                         }
224                         set {
225                                 ControlStyle.CssClass = value;
226                         }
227                 }
228
229                 [Bindable(true)]
230                 [DefaultValue(true)]
231 #if NET_2_0
232                 [Themeable (false)]
233 #endif          
234                 public virtual bool Enabled {
235                         get {
236                                 return enabled;
237                         }
238
239                         set {
240                                 if (enabled != value) {
241                                         if (IsTrackingViewState)
242                                                 track_enabled_state = true;
243                                         enabled = value;
244                                 }
245                         }
246                 }
247
248 #if NET_2_0
249                 [Browsable (true)]
250                 public virtual new bool EnableTheming
251                 {
252                         get { return base.EnableTheming; }
253                         set { base.EnableTheming = value; }
254                 }
255 #endif          
256
257 #if ONLY_1_1
258                 [DefaultValue(null)]
259 #endif          
260                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
261                 [NotifyParentProperty(true)]
262                 [WebSysDescription ("")]
263                 [WebCategory ("Appearance")]
264                 public virtual FontInfo Font {
265                         get {
266                                 // Oddly enough, it looks like we have to let it create the style
267                                 // since we can't create a FontInfo without a style owner
268                                 return ControlStyle.Font;
269                         }
270                 }
271
272 #if ONLY_1_1
273                 [Bindable(true)]
274 #endif          
275                 [DefaultValue(typeof (Color), "")]
276                 [TypeConverter(typeof(System.Web.UI.WebControls.WebColorConverter))]
277                 [WebSysDescription ("")]
278                 [WebCategory ("Appearance")]
279                 public virtual Color ForeColor {
280                         get {
281                                 if (style == null) 
282                                         return Color.Empty;
283                                 
284                                 return style.ForeColor;
285                         }
286                         set {
287                                 ControlStyle.ForeColor = value;
288                         }
289                 }
290
291                 [Browsable (false)]
292                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
293 #if NET_2_0
294                 public
295 #else
296                 internal
297 #endif
298                 bool HasAttributes 
299                 {
300                         get {
301                                 return (attributes != null && attributes.Count > 0);
302                         }
303                 }
304                 
305 #if ONLY_1_1
306                 [Bindable(true)]
307 #endif          
308                 [DefaultValue(typeof (Unit), "")]
309                 [WebSysDescription ("")]
310                 [WebCategory ("Layout")]
311                 public virtual Unit Height {
312                         get {
313                                 if (style == null) 
314                                         return Unit.Empty;
315                                 
316                                 return style.Height;
317                         }
318                         set {
319                                 ControlStyle.Height = value;
320                         }
321                 }
322
323 #if NET_2_0
324                 [Browsable (true)]
325                 public virtual new string SkinID
326                 {
327                         get { return base.SkinID; }
328                         set { base.SkinID = value; }
329                 }
330 #endif          
331                 
332                 [Browsable(false)]
333                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
334                 [WebSysDescription ("")]
335                 [WebCategory ("Style")]
336                 public CssStyleCollection Style {
337                         get {
338                                 return Attributes.CssStyle;
339                         }
340                 }
341
342                 [DefaultValue((short)0)]
343                 [WebSysDescription ("")]
344                 [WebCategory ("Behavior")]
345                 public virtual short TabIndex {
346                         get {
347                                 return ViewState.GetShort ("TabIndex", 0);
348                         }
349                         set {
350                                 ViewState ["TabIndex"] = value;
351                         }
352                 }
353
354 #if ONLY_1_1
355                 [Bindable(true)]
356 #endif          
357                 [DefaultValue("")]
358 #if NET_2_0
359                 [Localizable (true)]
360 #endif          
361                 [WebSysDescription ("")]
362                 [WebCategory ("Behavior")]
363                 public virtual string ToolTip {
364                         get {
365                                 return ViewState.GetString ("ToolTip", string.Empty);
366                         }
367                         set {
368                                 ViewState ["ToolTip"] = value;
369                         }
370                 }
371
372 #if ONLY_1_1
373                 [Bindable(true)]
374 #endif          
375                 [DefaultValue(typeof (Unit), "")]
376                 [WebSysDescription ("")]
377                 [WebCategory ("Layout")]
378                 public virtual Unit Width {
379                         get {
380                                 if (style == null) 
381                                         return Unit.Empty;
382                                 
383                                 return style.Width;
384                         }
385                         set {
386                                 ControlStyle.Width = value;
387                         }
388                 }
389
390                 [Browsable(false)]
391                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
392                 protected virtual HtmlTextWriterTag TagKey {
393                         get {
394                                 return tag;
395                         }
396                 }
397
398                 [Browsable(false)]
399                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
400                 protected virtual string TagName {
401                         get {
402                                 // do this here to avoid potentially costly lookups on every control
403                                 if (tag_name == null)
404                                         tag_name = HtmlTextWriter.StaticGetTagName (TagKey);
405                                 
406                                 return tag_name;
407                         }
408                 }
409
410 #if NET_2_0
411                 protected internal bool IsEnabled 
412                 {
413                         get {
414                                 WebControl wc = this;
415                                 while (wc != null) {
416                                         if (!wc.Enabled)
417                                                 return false;
418                                         wc = wc.Parent as WebControl;
419                                 }
420                                 return true;
421                         }
422                 }
423 #endif          
424                 
425
426                 public void ApplyStyle (Style s) 
427                 {
428                         if (s != null && !s.IsEmpty)
429                                 ControlStyle.CopyFrom(s);
430                 }
431
432                 public void CopyBaseAttributes (WebControl controlSrc) 
433                 {
434                         object o;
435
436                         if (controlSrc == null) 
437                                 return;
438
439                         Enabled = controlSrc.Enabled;
440
441                         o = controlSrc.ViewState ["AccessKey"];
442                         if (o != null)
443                                 ViewState ["AccessKey"] = o;
444
445                         o = controlSrc.ViewState ["TabIndex"];
446                         if (o != null)
447                                 ViewState ["TabIndex"] = o;
448
449                         o = controlSrc.ViewState ["ToolTip"];
450                         if (o != null)
451                                 ViewState ["ToolTip"] = o;
452
453                         if (controlSrc.attributes != null) {
454                                 AttributeCollection attributes = Attributes;
455                                 
456                                 foreach (string s in controlSrc.attributes.Keys)
457                                         attributes [s] = controlSrc.attributes [s];
458                         }
459                 }
460
461                 public void MergeStyle (Style s) 
462                 {
463                         if (s != null && !s.IsEmpty)
464                                 ControlStyle.MergeWith(s);
465                 }
466
467                 public virtual void RenderBeginTag (HtmlTextWriter writer)
468                 {
469                         AddAttributesToRender (writer);
470                         
471                         if (TagKey == HtmlTextWriterTag.Unknown)
472                                 writer.RenderBeginTag (TagName);
473                         else
474                                 writer.RenderBeginTag (TagKey);
475                         
476                 }
477
478                 public virtual void RenderEndTag (HtmlTextWriter writer) 
479                 {
480                         writer.RenderEndTag ();
481                 }
482
483                 static char[] _script_trim_chars = {';'};
484                 internal string BuildScriptAttribute (string name, string tail)
485                 {
486                         AttributeCollection attrs = Attributes;
487                         string attr = attrs [name];
488                         
489                         if (attr == null || attr.Length == 0)
490                                 return tail;
491                         if (attr [attr.Length - 1] == ';')
492                                 attr = attr.TrimEnd (_script_trim_chars);
493                         
494                         attr = String.Concat (attr, ";", tail);
495                         attrs.Remove (name);
496                         
497                         return attr;
498                 }
499                 
500 #if NET_2_0
501                 internal void AddDisplayStyleAttribute (HtmlTextWriter writer)
502                 {
503                         if (!ControlStyleCreated)
504                                 return;
505
506                         if (!ControlStyle.BorderWidth.IsEmpty ||
507                         (ControlStyle.BorderStyle != BorderStyle.None && ControlStyle.BorderStyle != BorderStyle.NotSet) ||
508                         !ControlStyle.Height.IsEmpty ||
509                         !ControlStyle.Width.IsEmpty)
510                                 writer.AddStyleAttribute (HtmlTextWriterStyle.Display, "inline-block");
511                 }
512 #endif
513
514                 protected virtual void AddAttributesToRender (HtmlTextWriter writer) 
515                 {
516                         if (ID != null)
517                                 writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
518
519                         if (AccessKey != string.Empty)
520                                 writer.AddAttribute (HtmlTextWriterAttribute.Accesskey, AccessKey);
521
522                         if (!enabled)
523                                 writer.AddAttribute (HtmlTextWriterAttribute.Disabled, "disabled", false);
524
525                         if (ToolTip != string.Empty)
526                                 writer.AddAttribute (HtmlTextWriterAttribute.Title, ToolTip);
527
528                         if (TabIndex != 0)
529                                 writer.AddAttribute (HtmlTextWriterAttribute.Tabindex, TabIndex.ToString ());
530
531                         if (style != null && !style.IsEmpty) {
532 #if NET_2_0
533                                 //unbelievable, but see WebControlTest.RenderBeginTag_BorderWidth_xxx
534                                 if (TagKey == HtmlTextWriterTag.Span)
535                                         AddDisplayStyleAttribute (writer);
536 #endif
537                                 style.AddAttributesToRender(writer, this);
538                         }
539
540                         if (attributes != null)
541                                 foreach(string s in attributes.Keys)
542                                         writer.AddAttribute (s, attributes [s]);
543                 }
544
545                 protected virtual Style CreateControlStyle() 
546                 {
547                         return new Style (ViewState);
548                 }
549
550                 protected override void LoadViewState (object savedState) 
551                 {
552                         if (savedState == null || !(savedState is Pair)) {
553                                 base.LoadViewState (null);
554                                 return;
555                         }
556
557                         Pair pair = (Pair) savedState;
558                         
559                         base.LoadViewState (pair.First);
560                         if (ViewState [System.Web.UI.WebControls.Style.BitStateKey] != null)
561                                 ControlStyle.LoadBitState ();
562
563                         if (pair.Second != null) {
564                                 if (attribute_state == null) {
565                                         attribute_state = new StateBag ();
566                                         if (IsTrackingViewState) 
567                                                 attribute_state.TrackViewState ();
568                                 }
569
570                                 attribute_state.LoadViewState (pair.Second);
571                                 attributes = new AttributeCollection(attribute_state);
572                         }
573
574                         enabled = ViewState.GetBool ("Enabled", enabled);
575                 }
576
577 #if NET_2_0
578                 protected internal
579 #else           
580                 protected
581 #endif          
582                 override void Render (HtmlTextWriter writer)
583                 {
584 #if NET_2_0
585                         if (Adapter != null) {
586                                 Adapter.Render(writer);
587                                 return;
588                         }
589 #endif
590                         RenderBeginTag (writer);
591                         RenderContents (writer);
592                         RenderEndTag (writer);
593                 }
594
595 #if NET_2_0
596                 protected internal
597 #else           
598                 protected
599 #endif          
600                 virtual void RenderContents (HtmlTextWriter writer)
601                 {
602                         base.Render (writer);
603                 }
604
605                 protected override object SaveViewState () 
606                 {
607                         if (track_enabled_state)
608                                 ViewState ["Enabled"] = enabled;
609
610                         object view_state;
611                         object attr_view_state = null;
612
613                         if (style != null)
614                                 style.SaveBitState ();
615                         view_state = base.SaveViewState ();
616
617                         if (attribute_state != null)
618                                 attr_view_state = attribute_state.SaveViewState ();
619                 
620                         if (view_state == null && attr_view_state == null)
621                                 return null;
622
623                         return new Pair (view_state, attr_view_state);
624                 }
625
626                 protected override void TrackViewState() 
627                 {
628                         if (style != null)
629                                 style.TrackViewState ();
630
631                         if (attribute_state != null) {
632                                 attribute_state.TrackViewState ();
633                                 attribute_state.SetDirty (true);
634                         }
635
636                         base.TrackViewState ();
637                 }
638
639                 string IAttributeAccessor.GetAttribute (string key) 
640                 {
641                         if (attributes != null)
642                                 return attributes [key];
643
644                         return null;
645                 }
646
647                 void IAttributeAccessor.SetAttribute (string key, string value) 
648                 {
649                         Attributes [key] = value;
650                 }
651         }
652 }