2007-01-07 Igor Zelmanovich <igorz@mainsoft.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / AdRotator.cs
1 // 
2 // System.Web.UI.WebControls.AdRotator
3 //
4 // Author:
5 //        Ben Maurer <bmaurer@novell.com>
6 //
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.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 using System.Xml;
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Security.Permissions;
33 using System.Web.Util;
34
35 namespace System.Web.UI.WebControls {
36
37         // CAS
38         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
39         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
40         // attributes
41         [DefaultEvent("AdCreated")]
42         [DefaultProperty("AdvertisementFile")]
43         [Designer("System.Web.UI.Design.WebControls.AdRotatorDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
44 #if NET_2_0
45         [ToolboxData("<{0}:AdRotator runat=\"server\"></{0}:AdRotator>")]
46 #else
47         [ToolboxData("<{0}:AdRotator runat=\"server\" Height=\"60px\" Width=\"468px\"></{0}:AdRotator>")]
48 #endif          
49         public class AdRotator :
50 #if NET_2_0
51         DataBoundControl
52 #else           
53         WebControl
54 #endif  
55         {
56 #if NET_2_0
57                 protected internal override void OnInit (EventArgs e)
58                 {
59                         base.OnInit(e);
60                 }
61 #endif
62                 
63 #if NET_2_0
64                 protected internal
65 #else           
66                 protected
67 #endif          
68                 override void OnPreRender (EventArgs eee)
69                 {
70                         Hashtable ht = null;
71                         
72                         if (ad_file != "" && ad_file != null) {
73                                 ReadAdsFromFile (Page.MapPath (ad_file));
74                                 ht = ChooseAd ();
75                         }
76
77                         AdCreatedEventArgs e = new AdCreatedEventArgs (ht);
78                         OnAdCreated (e);
79                         createdargs = e;
80                         
81                 }
82
83 #if NET_2_0
84                 [MonoTODO ("Not implemented")]
85                 protected internal override void PerformDataBinding (IEnumerable data)
86                 {
87                         throw new NotImplementedException ();
88                 }
89
90                 [MonoTODO ("Not implemented")]
91                 protected override void PerformSelect ()
92                 {
93                         throw new NotImplementedException ();
94                 }
95 #endif          
96
97                 AdCreatedEventArgs createdargs;
98
99 #if NET_2_0
100                 protected internal
101 #else           
102                 protected
103 #endif          
104                 override void Render (HtmlTextWriter w)
105                 {
106                         AdCreatedEventArgs e = createdargs;
107
108                         base.AddAttributesToRender (w);
109
110                         if (e.NavigateUrl != null && e.NavigateUrl.Length > 0)
111                                 w.AddAttribute (HtmlTextWriterAttribute.Href, ResolveAdUrl (e.NavigateUrl));
112                         if (Target != null && Target.Length > 0)
113                                 w.AddAttribute (HtmlTextWriterAttribute.Target, Target);
114                         
115                         w.RenderBeginTag (HtmlTextWriterTag.A);
116
117                         if (e.ImageUrl != null && e.ImageUrl.Length > 0)
118                                 w.AddAttribute (HtmlTextWriterAttribute.Src, ResolveAdUrl (e.ImageUrl));
119
120                         w.AddAttribute (HtmlTextWriterAttribute.Alt, e.AlternateText == null ? "" : e.AlternateText);
121                         w.AddAttribute (HtmlTextWriterAttribute.Border, "0");
122                         w.RenderBeginTag (HtmlTextWriterTag.Img);
123                         w.RenderEndTag (); // img
124                         w.RenderEndTag (); // a
125                 }
126
127                 string ResolveAdUrl (string url)
128                 {
129                         string path = url;
130                         
131                         if (AdvertisementFile != null && AdvertisementFile.Length > 0 && path [0] != '/' && path [0] != '~' 
132 #if NET_2_0
133                                 && !Uri.IsWellFormedUriString (path, UriKind.Absolute)
134 #endif
135                                 )
136                                 return UrlUtils.Combine (UrlUtils.GetDirectory (ResolveUrl (AdvertisementFile)), path);
137                         
138                         return ResolveUrl (path);
139                 }
140
141                 //
142                 // We take all the ads in the ad file and add up their
143                 // impression weight. We then take a random number [0,
144                 // TotalImpressions). We then choose the ad that is
145                 // that number or less impressions for the beginning
146                 // of the file. This lets us respect the weights
147                 // given.
148                 //
149                 Hashtable ChooseAd ()
150                 {
151                         // cache for performance
152                         string KeywordFilter = this.KeywordFilter;
153                         
154                         int total_imp = 0;
155                         int cur_imp = 0;
156                         
157                         foreach (Hashtable a in ads) {
158                                 if (KeywordFilter == "" || KeywordFilter == (string) a ["Keyword"])
159                                         total_imp += a ["Impressions"] != null ? int.Parse ((string) a ["Impressions"]) : 1;
160                         }
161
162                         int r = new Random ().Next (total_imp);
163
164                         foreach (Hashtable a in ads) {
165                                 if (KeywordFilter != "" && KeywordFilter != (string) a ["Keyword"])
166                                         continue;
167                                 cur_imp += a ["Impressions"] != null ? int.Parse ((string) a ["Impressions"]) : 1;
168                                 
169                                 if (cur_imp > r)
170                                         return a;
171                         }
172
173                         if (total_imp != 0)
174                                 throw new Exception ("I should only get here if no ads matched");
175                         
176                         return null;
177                 }
178
179                 ArrayList ads = new ArrayList ();
180                 
181                 void ReadAdsFromFile (string s)
182                 {
183                         XmlDocument d = new XmlDocument ();
184                         try {
185                                 d.Load (s);
186                         } catch (Exception e) {
187                                 throw new HttpException ("AdRotator could not parse the xml file", e);
188                         }
189                         
190                         ads.Clear ();
191                         
192                         foreach (XmlNode n in d.DocumentElement.ChildNodes) {
193
194                                 Hashtable ad = new Hashtable ();
195                                 
196                                 foreach (XmlNode nn in n.ChildNodes)
197                                         ad.Add (nn.Name, nn.InnerText);
198                                 
199                                 ads.Add (ad);
200                         }
201                 }
202                 
203                 string ad_file = "";
204
205 #if NET_2_0
206                 [UrlProperty]
207 #endif          
208                 [Bindable(true)]
209                 [DefaultValue("")]
210                 [Editor("System.Web.UI.Design.XmlUrlEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
211                 [WebSysDescription("")]
212                 [WebCategory("Behavior")]
213                 public string AdvertisementFile {
214                         get {
215                                 return ad_file;
216                         }
217                         set {
218                                 ad_file = value;
219                         }
220                         
221                 }
222
223 #if NET_2_0
224                 [DefaultValue ("AlternateText")]
225                 [WebSysDescriptionAttribute ("")]
226                 [WebCategoryAttribute ("Behavior")]
227                 [MonoTODO ("Not implemented")]
228                 public string AlternateTextField 
229                 {
230                         get {
231                                 throw new NotImplementedException ();
232                         }
233                         set {
234                                 throw new NotImplementedException ();
235                         }
236                 }
237 #endif          
238                 
239                 [Browsable(false)]
240                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
241                 [EditorBrowsable(EditorBrowsableState.Never)]
242                 public override FontInfo Font {
243                         get {
244                                 return base.Font;
245                         }
246                 }
247
248 #if NET_2_0
249                 [DefaultValue ("ImageUrl")]
250                 [MonoTODO ("Not implemented")]
251                 [WebSysDescriptionAttribute ("")]
252                 [WebCategoryAttribute ("Behavior")]
253                 public string ImageUrlField 
254                 {
255                         get {
256                                 throw new NotImplementedException ();
257                         }
258                         set {
259                                 throw new NotImplementedException ();
260                         }
261                 }
262 #endif          
263                 
264
265                 [Bindable(true)]
266                 [DefaultValue("")]
267                 [WebSysDescription("")]
268                 [WebCategory("Behavior")]
269                 public string KeywordFilter {
270                         get {
271                                 return ViewState.GetString ("KeywordFilter", "");
272                         }
273                         set {
274                                 ViewState ["KeywordFilter"] = value;
275                         }
276                         
277                 }
278
279 #if NET_2_0
280                 [DefaultValue ("NavigateUrl")]
281                 [MonoTODO ("Not implemented")]
282                 [WebSysDescriptionAttribute ("")]
283                 [WebCategoryAttribute ("Behavior")]
284                 public string NavigateUrlField 
285                 {
286                         get {
287                                 throw new NotImplementedException ();
288                         }
289                         set {
290                                 throw new NotImplementedException ();
291                         }
292                 }
293 #endif          
294                 
295                 [Bindable(true)]
296                 [DefaultValue("_top")]
297                 [TypeConverter(typeof(System.Web.UI.WebControls.TargetConverter))]
298                 [WebSysDescription("")]
299                 [WebCategory("Behavior")]
300                 public string Target {
301                         get {
302                                 return ViewState.GetString ("Target", "_top");
303                         }
304                         set {
305                                 ViewState ["Target"] = value;
306                         }
307                         
308                 }
309
310 #if NET_2_0
311                 /* all these are listed in corcompare */
312                 public override string UniqueID
313                 {
314                         get {
315                                 return base.UniqueID;
316                         }
317                 }
318
319                 protected override HtmlTextWriterTag TagKey 
320                 {
321                         get {
322                                 return base.TagKey;
323                         }
324                 }
325 #endif          
326         
327                 protected virtual void OnAdCreated (AdCreatedEventArgs e)
328                 {
329                         AdCreatedEventHandler h = (AdCreatedEventHandler) Events [AdCreatedEvent];
330                         if (h != null)
331                                 h (this, e);
332                 }
333
334                 static readonly object AdCreatedEvent = new object ();
335
336                 [WebSysDescription("")]
337                 [WebCategory("Action")]
338                 public event AdCreatedEventHandler AdCreated {
339                         add { Events.AddHandler (AdCreatedEvent, value); }
340                         remove { Events.RemoveHandler (AdCreatedEvent, value); }
341                 }
342         }
343 }