2007-05-07 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web / BrowserCapabilities.cs
1 // 
2 // System.Web.HttpBrowserCapabilities
3 //
4 // Authors:
5 //   Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2003 Novell, Inc. (http://www.novell.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections;
33 using System.Globalization;
34 using System.Web.Configuration;
35 using System.Web.UI;
36 using System.Security.Permissions;
37
38 #if NET_2_0
39 namespace System.Web.Configuration {
40         public partial class HttpCapabilitiesBase
41 #else
42
43 namespace System.Web {
44         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         public class HttpBrowserCapabilities : HttpCapabilitiesBase
47 #endif
48         {
49                 const int HaveActiveXControls = 1; // 1;
50                 const int HaveAdapters = 2;
51                 const int HaveAOL = 3; // 2;
52                 const int HaveBackGroundSounds = 4; // 3;
53                 const int HaveBeta = 5; // 4;
54                 const int HaveBrowser = 6; // 5;
55                 const int HaveBrowsers = 7;
56                 const int HaveCanCombineFormsInDeck = 8;
57                 const int HaveCanInitiateVoiceCall = 9;
58                 const int HaveCanRenderAfterInputOrSelectElement = 10;
59                 const int HaveCanRenderEmptySelects = 11;
60                 const int HaveCanRenderInputAndSelectElementsTogether = 12;
61                 const int HaveCanRenderMixedSelects = 13;
62                 const int HaveCanRenderOneventAndPrevElementsTogether = 14;
63                 const int HaveCanRenderPostBackCards = 15;
64                 const int HaveCanRenderSetvarZeroWithMultiSelectionList = 16;
65                 const int HaveCanSendMail = 17;
66                 const int HaveCDF = 18; // 6;
67                 //const int HaveClrVersion = 19; // 7;
68                 const int HaveCookies = 20; // 8;
69                 const int HaveCrawler = 21; // 9;
70                 const int HaveDefaultSubmitButtonLimit = 22;
71                 const int HaveEcmaScriptVersion = 23;
72                 const int HaveFrames = 24; // 11;
73                 const int HaveGatewayMajorVersion = 25;
74                 const int HaveGatewayMinorVersion = 26;
75                 const int HaveGatewayVersion = 27;
76                 const int HaveHasBackButton = 28;
77                 const int HaveHidesRightAlignedMultiselectScrollbars = 29;
78                 const int HaveHtmlTextWriter = 30;
79                 const int HaveId = 31;
80                 const int HaveInputType = 32;
81                 const int HaveIsColor = 33;
82                 const int HaveIsMobileDevice = 34;
83                 const int HaveJavaApplets = 35; // 12;
84                 const int HaveJavaScript = 36; // 13;
85                 const int HaveJScriptVersion = 37;
86                 const int HaveMajorVersion = 38; // 14;
87                 const int HaveMaximumHrefLength = 39;
88                 const int HaveMaximumRenderedPageSize = 40;
89                 const int HaveMaximumSoftkeyLabelLength = 41;
90                 const int HaveMinorVersion = 42; // 15;
91                 const int HaveMinorVersionString = 43;
92                 const int HaveMobileDeviceManufacturer = 44;
93                 const int HaveMobileDeviceModel = 45;
94                 const int HaveMSDomVersion = 46; // 16;
95                 const int HaveNumberOfSoftkeys = 47;
96                 const int HavePlatform = 48; // 17;
97                 const int HavePreferredImageMime = 49;
98                 const int HavePreferredRenderingMime = 50;
99                 const int HavePreferredRenderingType = 51;
100                 const int HavePreferredRequestEncoding = 52;
101                 const int HavePreferredResponseEncoding = 53;
102                 const int HaveRendersBreakBeforeWmlSelectAndInput = 54;
103                 const int HaveRendersBreaksAfterHtmlLists = 55;
104                 const int HaveRendersBreaksAfterWmlAnchor = 56;
105                 const int HaveRendersBreaksAfterWmlInput = 57;
106                 const int HaveRendersWmlDoAcceptsInline = 58;
107                 const int HaveRendersWmlSelectsAsMenuCards = 59;
108                 const int HaveRequiredMetaTagNameValue = 60;
109                 const int HaveRequiresAttributeColonSubstitution = 61;
110                 const int HaveRequiresContentTypeMetaTag = 62;
111                 const int HaveRequiresControlStateInSession = 63;
112                 const int HaveRequiresDBCSCharacter = 64;
113                 const int HaveRequiresHtmlAdaptiveErrorReporting = 65;
114                 const int HaveRequiresLeadingPageBreak = 66;
115                 const int HaveRequiresNoBreakInFormatting = 67;
116                 const int HaveRequiresOutputOptimization = 68;
117                 const int HaveRequiresPhoneNumbersAsPlainText = 69;
118                 const int HaveRequiresSpecialViewStateEncoding = 70;
119                 const int HaveRequiresUniqueFilePathSuffix = 71;
120                 const int HaveRequiresUniqueHtmlCheckboxNames = 72;
121                 const int HaveRequiresUniqueHtmlInputNames = 73;
122                 const int HaveRequiresUrlEncodedPostfieldValues = 74;
123                 const int HaveScreenBitDepth = 75;
124                 const int HaveScreenCharactersHeight = 76;
125                 const int HaveScreenCharactersWidth = 77;
126                 const int HaveScreenPixelsHeight = 78;
127                 const int HaveScreenPixelsWidth = 79;
128                 const int HaveSupportsAccesskeyAttribute = 80;
129                 const int HaveSupportsBodyColor = 81;
130                 const int HaveSupportsBold = 82;
131                 const int HaveSupportsCacheControlMetaTag = 83;
132                 const int HaveSupportsCallback = 84;
133                 const int HaveSupportsCss = 85;
134                 const int HaveSupportsDivAlign = 86;
135                 const int HaveSupportsDivNoWrap = 87;
136                 const int HaveSupportsEmptyStringInCookieValue = 88;
137                 const int HaveSupportsFontColor = 89;
138                 const int HaveSupportsFontName = 90;
139                 const int HaveSupportsFontSize = 91;
140                 const int HaveSupportsImageSubmit = 92;
141                 const int HaveSupportsIModeSymbols = 93;
142                 const int HaveSupportsInputIStyle = 94;
143                 const int HaveSupportsInputMode = 95;
144                 const int HaveSupportsItalic = 96;
145                 const int HaveSupportsJPhoneMultiMediaAttributes = 97;
146                 const int HaveSupportsJPhoneSymbols = 98;
147                 const int HaveSupportsQueryStringInFormAction = 99;
148                 const int HaveSupportsRedirectWithCookie = 100;
149                 const int HaveSupportsSelectMultiple = 101;
150                 const int HaveSupportsUncheck = 102;
151                 const int HaveSupportsXmlHttp = 103;
152                 const int HaveTables = 104; // 18;
153                 //const int HaveTagWriter = 105; // 19;
154                 const int HaveType = 106;
155                 const int HaveUseOptimizedCacheKey = 107;
156                 const int HaveVBScript = 108; // 20;
157                 const int HaveVersion = 109; // 21;
158                 const int HaveW3CDomVersion = 110; // 22;
159                 const int HaveWin16 = 111; // 23;
160                 const int HaveWin32 = 112; // 24;
161                 const int LastHaveFlag = 113;
162
163                 BitArray flags = new BitArray (LastHaveFlag);
164                 bool activeXControls;
165                 bool aol;
166                 bool backgroundSounds;
167                 bool beta;
168                 string browser;
169                 bool cdf;
170                 Version clrVersion;
171                 bool cookies;
172                 bool crawler;
173                 Version ecmaScriptVersion;
174                 bool frames;
175                 bool javaApplets;
176                 bool javaScript;
177                 int majorVersion;
178                 double minorVersion;
179                 Version msDomVersion;
180                 string platform;
181                 bool tables;
182                 //Type tagWriter;
183                 bool vbscript;
184                 string version;
185                 Version w3CDomVersion;
186                 bool win16;
187                 bool win32;
188                 Version [] clrVersions;
189                 internal string useragent;
190
191 #if !NET_2_0
192                 public HttpBrowserCapabilities ()
193                 {
194                 }
195 #endif
196
197                 public bool ActiveXControls {
198                         get {
199                                 if (!Get (HaveActiveXControls)) {
200                                         activeXControls = ReadBoolean ("activexcontrols");
201                                         Set (HaveActiveXControls);
202                                 }
203
204                                 return activeXControls;
205                         }
206                 }
207
208                 public bool AOL {
209                         get {
210                                 if (!Get (HaveAOL)) {
211                                         aol = ReadBoolean ("aol");
212                                         Set (HaveAOL);
213                                 }
214
215                                 return aol;
216                         }
217                 }
218
219                 public bool BackgroundSounds {
220                         get {
221                                 if (!Get (HaveBackGroundSounds)) {
222                                         backgroundSounds = ReadBoolean ("backgroundsounds");
223                                         Set (HaveBackGroundSounds);
224                                 }
225
226                                 return backgroundSounds;
227                         }
228                 }
229
230                 public bool Beta {
231                         get {
232                                 if (!Get (HaveBeta)) {
233                                         beta = ReadBoolean ("beta");
234                                         Set (HaveBeta);
235                                 }
236
237                                 return beta;
238                         }
239                 }
240
241                 public string Browser {
242                         get {
243                                 if (!Get (HaveBrowser)) {
244                                         browser = this ["browser"];
245                                         if (browser == null || browser.Length == 0)
246                                                 browser = "Unknown";
247                                         Set (HaveBrowser);
248                                 }
249
250                                 return browser;
251                         }
252                 }
253 #if NET_2_0
254                 ArrayList browsers = null;
255                 public ArrayList Browsers {
256                         get {
257                                 if (!Get (HaveBrowsers)) {
258                                         browsers = ReadArrayList ("browsers");
259                                         Set (HaveBrowsers);
260                                 }
261
262                                 return browsers;
263                         }
264                 }
265
266                 public bool IsBrowser (string browserName) 
267                 {
268                         foreach (string browser in Browsers) {
269                                 if (0 == String.CompareOrdinal(browser, "Unknown")) {
270                                         continue;
271                                 }
272                                 if (0 == String.CompareOrdinal(browserName, browser)) {
273                                         return true;
274                                 }
275                         }
276                         return false;
277                 }
278 #endif
279                 public bool CDF {
280                         get {
281                                 if (!Get (HaveCDF)) {
282                                         cdf = ReadBoolean ("cdf");
283                                         Set (HaveCDF);
284                                 }
285
286                                 return cdf;
287                         }
288                 }
289
290                 public Version ClrVersion {
291                         get {
292                                 if (clrVersion == null)
293                                         InternalGetClrVersions ();
294
295                                 return clrVersion;
296                         }
297                 }
298
299                 public bool Cookies {
300                         get {
301                                 if (!Get (HaveCookies)) {
302                                         cookies = ReadBoolean ("cookies");
303                                         Set (HaveCookies);
304                                 }
305
306                                 return cookies;
307                         }
308                 }
309
310                 public bool Crawler {
311                         get {
312                                 if (!Get (HaveCrawler)) {
313                                         crawler = ReadBoolean ("crawler");
314                                         Set (HaveCrawler);
315                                 }
316
317                                 return crawler;
318                         }
319                 }
320
321                 public Version EcmaScriptVersion {
322                         get {
323                                 if (!Get (HaveEcmaScriptVersion)) {
324                                         ecmaScriptVersion = ReadVersion ("ecmascriptversion");
325                                         Set (HaveEcmaScriptVersion);
326                                 }
327
328                                 return ecmaScriptVersion;
329                         }
330                 }
331
332                 public bool Frames {
333                         get {
334                                 if (!Get (HaveFrames)) {
335                                         frames = ReadBoolean ("frames");
336                                         Set (HaveFrames);
337                                 }
338
339                                 return frames;
340                         }
341                 }
342
343                 public bool JavaApplets {
344                         get {
345                                 if (!Get (HaveJavaApplets)) {
346                                         javaApplets = ReadBoolean ("javaapplets");
347                                         Set (HaveJavaApplets);
348                                 }
349
350                                 return javaApplets;
351                         }
352                 }
353
354                 public bool JavaScript {
355                         get {
356                                 if (!Get (HaveJavaScript)) {
357                                         javaScript = ReadBoolean ("javascript");
358                                         Set (HaveJavaScript);
359                                 }
360
361                                 return javaScript;
362                         }
363                 }
364
365                 public int MajorVersion {
366                         get {
367                                 if (!Get (HaveMajorVersion)) {
368                                         majorVersion = ReadInt32 ("majorver");
369                                         Set (HaveMajorVersion);
370                                 }
371
372                                 return majorVersion;
373                         }
374                 }
375
376                 public double MinorVersion {
377                         get {
378                                 if (!Get (HaveMinorVersion)) {
379                                         minorVersion = ReadDouble ("minorver");
380                                         Set (HaveMinorVersion);
381                                 }
382
383                                 return minorVersion;
384                         }
385                 }
386
387                 public Version MSDomVersion {
388                         get {
389                                 if (!Get (HaveMSDomVersion)) {
390                                         msDomVersion = ReadVersion ("msdomversion");
391                                         Set (HaveMSDomVersion);
392                                 }
393
394                                 return msDomVersion;
395                         }
396                 }
397
398                 public string Platform {
399                         get {
400                                 if (!Get (HavePlatform)) {
401                                         platform = ReadString ("platform");
402                                         Set (HavePlatform);
403                                 }
404
405                                 return platform;
406                         }
407                 }
408
409                 public bool Tables {
410                         get {
411                                 if (!Get (HaveTables)) {
412                                         tables = ReadBoolean ("tables");
413                                         Set (HaveTables);
414                                 }
415
416                                 return tables;
417                         }
418                 }
419
420                 public Type TagWriter {
421                         get {
422                                 return typeof (HtmlTextWriter);
423                         }
424                 }
425
426                 public string Type {
427                         get {
428                                 return Browser + MajorVersion;
429                         }
430                 }
431
432                 public bool VBScript {
433                         get {
434                                 if (!Get (HaveVBScript)) {
435                                         vbscript = ReadBoolean ("vbscript");
436                                         Set (HaveVBScript);
437                                 }
438
439                                 return vbscript;
440                         }
441                 }
442
443                 public string Version {
444                         get {
445                                 if (!Get (HaveVersion)) {
446                                         version = ReadString ("version");
447                                         Set (HaveVersion);
448                                 }
449
450                                 return version;
451                         }
452                 }
453
454                 public Version W3CDomVersion {
455                         get {
456                                 if (!Get (HaveW3CDomVersion)) {
457                                         w3CDomVersion = ReadVersion ("w3cdomversion");
458                                         Set (HaveW3CDomVersion);
459                                 }
460
461                                 return w3CDomVersion;
462                         }
463                 }
464
465                 public bool Win16 {
466                         get {
467                                 if (!Get (HaveWin16)) {
468                                         win16 = ReadBoolean ("win16");
469                                         Set (HaveWin16);
470                                 }
471
472                                 return win16;
473                         }
474                 }
475
476                 public bool Win32 {
477                         get {
478                                 // This is the list of different windows platforms that browscap.ini has.
479                                 // Win16 Win2000 Win2003 Win32 Win95 Win98 WinME WinNT WinVI WinXP
480                                 if (!Get (HaveWin32)) {
481                                         string platform = Platform;
482                                         win32 = (platform != "Win16" && platform.StartsWith ("Win"));
483                                         Set (HaveWin32);
484                                 }
485                                 return win32;
486                         }
487                 }
488
489 #if NET_1_1
490                 public Version [] GetClrVersions ()
491                 {
492                         if (clrVersions == null)
493                                 InternalGetClrVersions ();
494
495                         return clrVersions;
496                 }
497 #endif
498
499                 void InternalGetClrVersions ()
500                 {
501                         char [] anychars = new char [] { ';', ')' };
502                         string s = useragent;
503                         ArrayList list = null;
504                         int idx;
505                         while ((s != null) && (idx = s.IndexOf (".NET CLR ")) != -1) {
506                                 int end = s.IndexOfAny (anychars, idx + 9);
507                                 if (end == -1)
508                                         break;
509
510                                 string ver = s.Substring (idx + 9, end - idx - 9);
511                                 Version v = null;
512                                 try {
513                                         v = new Version (ver);
514                                         if (clrVersion == null || v > clrVersion)
515                                                 clrVersion = v;
516
517                                         if (list == null)
518                                                 list = new ArrayList (4);
519
520                                         list.Add (v);
521                                 } catch { }
522                                 s = s.Substring (idx + 9);
523                         }
524                         
525                         if (list == null || list.Count == 0) {
526                                 clrVersion = new Version ();
527 #if NET_2_0
528                                 clrVersions = null;
529 #else
530                                 clrVersions = new Version [1] { clrVersion };
531 #endif
532                         } else {
533                                 list.Sort ();
534                                 clrVersions = (Version []) list.ToArray (typeof (Version));
535                         }
536                 }
537
538                 bool ReadBoolean (string key)
539                 {
540                         string v = this [key];
541                         if (v == null) {
542                                 throw CreateCapabilityNotFoundException (key);
543                         }
544
545                         return (String.Compare (v, "True", true, CultureInfo.InvariantCulture) == 0);
546                 }
547
548                 int ReadInt32 (string key)
549                 {
550                         string v = this [key];
551                         if (v == null) {
552                                 throw CreateCapabilityNotFoundException (key);
553                         }
554
555                         try {
556                                 return Int32.Parse (v);
557                         } catch {
558                                 throw CreateCapabilityNotFoundException (key);
559                         }
560                 }
561
562                 double ReadDouble (string key)
563                 {
564                         string v = this [key];
565                         if (v == null) {
566                                 throw CreateCapabilityNotFoundException (key);
567                         }
568
569                         try {
570                                 return Double.Parse (v);
571                         } catch {
572                                 throw CreateCapabilityNotFoundException (key);
573                         }
574                 }
575
576                 private string ReadString (string key) 
577                 {
578                         string v = this [key];
579                         if (v == null) {
580                                 throw CreateCapabilityNotFoundException (key);
581                         }
582
583                         return v;
584                 }
585
586                 Version ReadVersion (string key) 
587                 {
588                         string v = this [key];
589                         if (v == null) {
590                                 throw CreateCapabilityNotFoundException (key);
591                         }
592
593                         try {
594                                 return new Version (v);
595                         }
596                         catch {
597                                 throw CreateCapabilityNotFoundException (key);
598                         }
599                 }
600
601 #if NET_2_0
602                 private ArrayList ReadArrayList (string key) 
603                 {
604                         ArrayList v = (ArrayList)this.capabilities [key];
605                         if (v == null) {
606                                 throw CreateCapabilityNotFoundException (key);
607                         }
608
609                         return v;
610                 }
611 #endif
612                 Exception CreateCapabilityNotFoundException (string key) {
613                         return new ArgumentNullException (String.Format ("browscaps.ini does not contain a definition for capability {0} for userAgent {1}", key, Browser));
614                 }
615
616                 bool Get (int idx)
617                 {
618                         return flags.Get (idx);
619                 }
620
621                 void Set (int idx)
622                 {
623                         flags.Set (idx, true);
624                 }
625         }
626 }