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