2 Copyright (C) 2000-2008 SKYRIX Software AG
3 Copyright (C) 2006-2008 Helge Hess
5 This file is part of SOPE.
7 SOPE is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with SOPE; see the file COPYING. If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include <NGObjWeb/WEClientCapabilities.h>
24 #include <NGObjWeb/WOAssociation.h>
25 #include <NGObjWeb/WOContext.h>
26 #include <NGObjWeb/WOComponent.h>
27 #include <NGObjWeb/WOResponse.h>
31 #define WEUA_UNKNOWN 0
33 #define WEUA_Netscape 2
39 #define WEUA_WebFolder 8
40 #define WEUA_Mozilla 9
41 #define WEUA_OmniWeb 10
43 #define WEUA_Konqueror 12
46 #define WEUA_CADAVER 15
47 #define WEUA_GOLIVE 16
48 #define WEUA_MACOSX_DAVFS 17
50 #define WEUA_JavaSDK 19
51 #define WEUA_PythonURLLIB 20
52 #define WEUA_AppleDAVAccess 21
53 #define WEUA_MSWebPublisher 22
55 #define WEUA_Evolution 24
56 #define WEUA_MSOutlook 25
57 #define WEUA_MSOutlookExpress 26
58 #define WEUA_GNOMEVFS 27
59 #define WEUA_ZideLook 28
60 #define WEUA_Safari 29
62 #define WEUA_Entourage 31
63 #define WEUA_NetNewsWire 32
64 #define WEUA_xmlrpclib_py 33
65 #define WEUA_Morgul 34
66 #define WEUA_CFNetwork 35
67 #define WEUA_KungLog 36
70 #define WEUA_NewsFire 39
71 #define WEUA_Goliath 40
72 #define WEUA_PerlHTTPDAV 41
73 #define WEUA_Google 42
74 #define WEUA_WebDrive 43
75 #define WEUA_Sunbird 44
76 #define WEUA_PEAR_XMLRPC 45
77 #define WEUA_Cook_XMLRPCdotNET 46
79 #define WEUA_ZideOne_Outlook 48
81 #define WEOS_UNKNOWN 0
82 #define WEOS_WINDOWS 1
87 #define WECPU_UNKNOWN 0
92 @interface WEClientCapabilities(Privates)
93 - (id)initWithRequest:(WORequest *)_request;
96 @implementation WEClientCapabilities
98 - (id)initWithRequest:(WORequest *)_request {
102 int defaultOS = WEOS_UNKNOWN;
103 int defaultCPU = WECPU_UNKNOWN;
107 if ((ac = [_request headerForKey:@"accept-charset"])) {
108 /* not really correct ..., eg could have quality "0" ! */
109 ac = [ac lowercaseString];
110 if ([ac rangeOfString:@"utf-8"].length > 0)
111 self->flags.acceptUTF8 = 1;
114 /* process user-agent */
116 self->userAgent = [[_request headerForKey:@"user-agent"] copy];
117 #if LIB_FOUNDATION_LIBRARY
118 ua = [self->userAgent cString];
120 ua = [self->userAgent UTF8String];
123 /* no user-agent, eg telnet */
129 if ((tmp = strstr(ua, "Opera"))) {
130 /* Opera (can fake to be MSIE or Netscape) */
131 self->browser = WEUA_Opera;
133 /* go to next space */
134 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
136 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
138 self->browserMajorVersion = atoi(tmp);
139 if ((tmp = index(tmp, '.'))) {
141 self->browserMinorVersion = atoi(tmp);
144 else if (strstr(ua, "NeonConnection") != NULL ||
145 strstr(ua, "ZIDEStore") != NULL ||
146 strstr(ua, "ZideLook-Codeon") != NULL) {
147 self->browser = WEUA_ZideLook;
148 self->browserMinorVersion = 0;
149 self->browserMajorVersion = 0;
151 else if (strstr(ua, "ZideOne/") != NULL) {
152 self->browser = WEUA_ZideOne_Outlook;
153 self->browserMinorVersion = 0;
154 self->browserMajorVersion = 0;
156 else if ((tmp = strstr(ua, "Safari/"))) {
157 /* Hm, Safari says it is a Mozilla/5.0 ? */
159 self->browser = WEUA_Safari;
160 tmp += 7; /* skip "Safari/" */
161 combinedVersion = atoi(tmp);
162 /* well, don't know how this is supposed to work? 100=v1.1 */
163 if (combinedVersion == 100 /* 100 is v1.1 */) {
164 self->browserMajorVersion = 1;
165 self->browserMinorVersion = 1;
168 /* watch for upcoming versions ... */
169 self->browserMajorVersion = combinedVersion / 100;
172 else if ((tmp = strstr(ua, "Sunbird/"))) {
173 /* Sunbird says it is a Mozilla */
174 self->browser = WEUA_Sunbird;
175 tmp += 8; /* skip "Sunbird/" */
177 self->browserMajorVersion = atoi(tmp);
178 if ((tmp = index(tmp, '.'))) {
180 self->browserMinorVersion = atoi(tmp);
183 else if (strstr(ua, "Outlook-Express/")) {
184 /* Outlook Express 5.5 mailbox access via http */
185 self->browser = WEUA_MSOutlookExpress;
187 else if (strstr(ua, "Outlook Express/")) {
188 /* Outlook Express 5.0 mailbox access via http */
189 self->browser = WEUA_MSOutlookExpress;
191 else if (strstr(ua, "Microsoft-Outlook/")) {
192 /* Outlook 2002 mailbox access via http */
193 self->browser = WEUA_MSOutlook;
195 else if (strstr(ua, "Microsoft HTTP Post")) {
196 /* Outlook 2000 with WebPublishing Assistent */
197 self->browser = WEUA_MSWebPublisher;
199 else if (strstr(ua, "Entourage/10")) {
200 /* Entourage MacOSX 10.1.4 */
201 self->browser = WEUA_Entourage;
203 else if (strstr(ua, "Microsoft-WebDAV-MiniRedir/5")) {
204 /* WebFolders Win XP SP 2 */
205 self->browser = WEUA_WebFolder;
207 else if ((tmp = strstr(ua, "MSIE"))) {
208 /* Internet Explorer */
209 self->browser = WEUA_IE;
211 /* go to next space */
212 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
214 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
216 self->browserMajorVersion = atoi(tmp);
217 if ((tmp = index(tmp, '.'))) {
219 self->browserMinorVersion = atoi(tmp);
222 else if ((tmp = strstr(ua, "Konqueror"))) {
223 /* Konqueror (KDE2 FileManager) */
224 self->browser = WEUA_Konqueror;
226 if ((tmp = index(tmp, '/'))) {
228 self->browserMajorVersion = atoi(tmp);
229 if ((tmp = index(tmp, '.'))) {
231 self->browserMinorVersion = atoi(tmp);
235 else if ((tmp = strstr(ua, "Netscape6"))) {
237 self->browser = WEUA_Netscape;
239 if ((tmp = index(tmp, '/'))) {
241 self->browserMajorVersion = atoi(tmp);
242 if ((tmp = index(tmp, '.'))) {
244 self->browserMinorVersion = atoi(tmp);
248 else if (strstr(ua, "Lynx")) {
250 self->browser = WEUA_Lynx;
252 else if (strstr(ua, "Links")) {
254 self->browser = WEUA_Links;
256 else if (strstr(ua, "gnome-vfs")) {
258 self->browser = WEUA_GNOMEVFS;
260 else if (strstr(ua, "cadaver")) {
261 /* Cadaver DAV browser */
262 self->browser = WEUA_CADAVER;
264 else if (strstr(ua, "GoLive")) {
266 self->browser = WEUA_GOLIVE;
268 else if (strstr(ua, "DAV.pm")) {
270 self->browser = WEUA_PerlHTTPDAV;
272 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "fetch/") != NULL) {
273 /* MacOSX 10.0 DAV FileSystem */
274 self->browser = WEUA_MACOSX_DAVFS;
276 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "WebDAVFS/") != NULL) {
277 /* MacOSX DAV FileSystem */
278 self->browser = WEUA_MACOSX_DAVFS;
280 else if (strstr(ua, "OmniWeb")) {
282 self->browser = WEUA_OmniWeb;
284 else if (strstr(ua, "Evolution")) {
286 self->browser = WEUA_Evolution;
288 else if (strstr(ua, "wdfs/")) {
290 self->browser = WEUA_WDFS;
292 else if (strstr(ua, "Soup/")) {
293 /* SOUP (GNOME WebDAV library) */
294 self->browser = WEUA_SOUP;
296 else if (strstr(ua, "amaya")) {
298 self->browser = WEUA_Amaya;
300 else if (strstr(ua, "NetNewsWire/")) {
302 self->browser = WEUA_NetNewsWire;
304 else if (strstr(ua, "Dillo")) {
306 self->browser = WEUA_Dillo;
308 else if (strstr(ua, "Java")) {
310 self->browser = WEUA_JavaSDK;
312 else if (strstr(ua, "Python-urllib")) {
313 /* Python URL module */
314 self->browser = WEUA_PythonURLLIB;
316 else if (strstr(ua, "xmlrpclib.py/")) {
317 /* Python XML-RPC module */
318 self->browser = WEUA_xmlrpclib_py;
320 else if (strstr(ua, "Emacs")) {
322 self->browser = WEUA_Emacs;
324 else if (strstr(ua, "iCab")) {
326 self->browser = WEUA_iCab;
328 else if (strstr(ua, "Wget")) {
330 self->browser = WEUA_Wget;
332 else if (strstr(ua, "DAVAccess")) {
333 /* Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework */
334 self->browser = WEUA_AppleDAVAccess;
336 else if (strstr(ua, "DAVKit/")) {
337 /* some iCal 1.x DAV Access Framework, report as Apple DAV access */
338 self->browser = WEUA_AppleDAVAccess;
340 else if (strstr(ua, "Microsoft Data Access Internet Publishing Provider")) {
342 self->browser = WEUA_WebFolder;
344 else if (strstr(ua, "Microsoft Office Protocol Discovery")) {
345 /* Word 2003, treat as WebFolder */
346 self->browser = WEUA_WebFolder;
348 else if (strstr(ua, "curl")) {
350 self->browser = WEUA_CURL;
352 else if (strstr(ua, "Mozilla")) {
353 /* other Netscape browser */
354 if (strstr(ua, "Mozilla/5")) {
355 self->browser = WEUA_Mozilla;
356 self->browserMajorVersion = 5;
358 else if (strstr(ua, "Mozilla/4")) {
359 self->browser = WEUA_Netscape;
360 self->browserMajorVersion = 4;
363 NSLog(@"%s: Unknown Mozilla Browser: user-agent='%@'",
364 __PRETTY_FUNCTION__, self->userAgent);
367 else if (strstr(ua, "Morgul")) {
368 self->browser = WEUA_Morgul;
370 else if (strstr(ua, "WebDrive")) {
371 self->browser = WEUA_WebDrive;
373 else if (strstr(ua, "CFNetwork/1.1")) {
374 self->browser = WEUA_CFNetwork;
376 else if (strstr(ua, "Kung-Log/")) {
377 self->browser = WEUA_KungLog;
379 else if (strstr(ua, "ecto")) {
380 self->browser = WEUA_Ecto;
382 else if (strstr(ua, "NewsFire")) {
383 self->browser = WEUA_NewsFire;
385 else if (strstr(ua, "Goliath")) {
386 self->browser = WEUA_Goliath;
388 else if (strstr(ua, "SOPE/")) {
389 self->browser = WEUA_SOPE;
391 else if (strstr(ua, "Mediapartners-Google/")) {
392 self->browser = WEUA_Google;
394 else if (strstr(ua, "PEAR XML_RPC")) {
395 self->browser = WEUA_PEAR_XMLRPC;
397 else if (strstr(ua, "XML-RPC.NET")) {
398 self->browser = WEUA_Cook_XMLRPCdotNET;
401 /* unknown browser */
402 self->browser = WEUA_UNKNOWN;
404 if (self->userAgent) {
405 NSLog(@"%s: Unknown WebClient: user-agent='%@'",
406 __PRETTY_FUNCTION__, self->userAgent);
412 if (strstr(ua, "Windows") != NULL || strstr(ua, "WinNT") != NULL)
413 self->os = WEOS_WINDOWS;
414 else if (strstr(ua, "Linux"))
415 self->os = WEOS_LINUX;
416 else if (strstr(ua, "Mac"))
417 self->os = WEOS_MACOS;
418 else if (strstr(ua, "SunOS"))
419 self->os = WEOS_SUNOS;
421 self->os = defaultOS;
425 if (strstr(ua, "sun4u"))
426 self->cpu = WECPU_SPARC;
427 else if (strstr(ua, "i686") || strstr(ua, "i586"))
428 self->cpu = WECPU_IX86;
429 else if (strstr(ua, "PowerPC") || strstr(ua, "ppc") || strstr(ua, "PPC"))
430 self->cpu = WECPU_PPC;
431 else if (self->os == WEOS_WINDOWS)
432 /* assume ix86 if OS is Windows .. */
433 self->cpu = WECPU_IX86;
435 self->cpu = defaultCPU;
441 [self->userAgent release];
447 - (NSString *)userAgent {
448 return self->userAgent;
451 - (NSString *)userAgentType {
452 switch (self->browser) {
453 case WEUA_IE: return @"IE";
454 case WEUA_Netscape: return @"Netscape";
455 case WEUA_Lynx: return @"Lynx";
456 case WEUA_Links: return @"Links";
457 case WEUA_Opera: return @"Opera";
458 case WEUA_Amaya: return @"Amaya";
459 case WEUA_Emacs: return @"Emacs";
460 case WEUA_Wget: return @"Wget";
461 case WEUA_WebFolder: return @"WebFolder";
462 case WEUA_DAVFS: return @"DAVFS";
463 case WEUA_MACOSX_DAVFS: return @"MacOSXDAVFS";
464 case WEUA_CADAVER: return @"Cadaver";
465 case WEUA_GOLIVE: return @"GoLive";
466 case WEUA_Mozilla: return @"Mozilla";
467 case WEUA_OmniWeb: return @"OmniWeb";
468 case WEUA_iCab: return @"iCab";
469 case WEUA_Konqueror: return @"Konqueror";
470 case WEUA_Dillo: return @"Dillo";
471 case WEUA_JavaSDK: return @"Java";
472 case WEUA_PythonURLLIB: return @"Python-urllib";
473 case WEUA_AppleDAVAccess: return @"AppleDAVAccess";
474 case WEUA_MSWebPublisher: return @"MSWebPublisher";
475 case WEUA_CURL: return @"CURL";
476 case WEUA_Evolution: return @"Evolution";
477 case WEUA_SOUP: return @"SOUP";
478 case WEUA_MSOutlook: return @"MSOutlook";
479 case WEUA_MSOutlookExpress: return @"MSOutlookExpress";
480 case WEUA_GNOMEVFS: return @"GNOME-VFS";
481 case WEUA_ZideLook: return @"ZideLook";
482 case WEUA_Safari: return @"Safari";
483 case WEUA_Entourage: return @"Entourage";
484 case WEUA_NetNewsWire: return @"NetNewsWire";
485 case WEUA_xmlrpclib_py: return @"xmlrpclib.py";
486 case WEUA_Morgul: return @"Morgul";
487 case WEUA_KungLog: return @"KungLog";
488 case WEUA_Ecto: return @"Ecto";
489 case WEUA_NewsFire: return @"NewsFire";
490 case WEUA_Goliath: return @"Goliath";
491 case WEUA_PerlHTTPDAV: return @"PerlHTTPDAV";
492 case WEUA_Google: return @"Google";
493 case WEUA_WebDrive: return @"WebDrive";
494 case WEUA_Sunbird: return @"Sunbird";
495 case WEUA_PEAR_XMLRPC: return @"PHP PEAR XMLRPC";
496 case WEUA_Cook_XMLRPCdotNET: return @"PHP PEAR XMLRPC";
497 case WEUA_WDFS: return @"WDFS";
498 case WEUA_ZideOne_Outlook: return @"ZideOne";
499 default: return @"unknown";
504 case WEOS_WINDOWS: return @"Windows";
505 case WEOS_LINUX: return @"Linux";
506 case WEOS_MACOS: return @"MacOS";
507 case WEOS_SUNOS: return @"SunOS";
508 default: return @"unknown";
513 case WECPU_IX86: return @"ix86";
514 case WECPU_SPARC: return @"sparc";
515 case WECPU_PPC: return @"ppc";
516 default: return @"unknown";
520 - (unsigned char)majorVersion {
521 return self->browserMajorVersion;
523 - (unsigned char)minorVersion {
524 return self->browserMinorVersion;
527 /* browser capabilities */
529 - (BOOL)isJavaScriptBrowser {
530 switch (self->browser) {
544 - (BOOL)isVBScriptBrowser {
545 switch (self->browser) {
554 - (BOOL)isFastTableBrowser {
555 switch (self->browser) {
567 return (self->browserMajorVersion >= 6)
575 - (BOOL)isCSS2Browser {
576 switch (self->browser) {
577 case WEUA_IE: return (self->browserMajorVersion >= 5) ? YES : NO;
578 case WEUA_Netscape: return (self->browserMajorVersion >= 6) ? YES : NO;
579 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
580 case WEUA_Mozilla: return YES;
581 case WEUA_Safari: return YES;
582 case WEUA_Konqueror: return NO;
587 - (BOOL)isCSS1Browser {
588 switch (self->browser) {
589 case WEUA_IE: return (self->browserMajorVersion >= 4) ? YES : NO;
590 case WEUA_Netscape: return (self->browserMajorVersion >= 4) ? YES : NO;
591 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
592 case WEUA_Safari: return YES;
593 case WEUA_Konqueror: return NO;
598 - (BOOL)ignoresCSSOnFormElements {
599 if (self->browser == WEUA_Safari) /* Safari always displays Aqua buttons */
602 return [self isCSS1Browser] ? NO : YES;
605 - (BOOL)isXULBrowser {
606 if (self->browser == WEUA_Safari) // TODO: Safari supports some XUL stuff
608 if ((self->browser == WEUA_Netscape) && (self->browserMajorVersion >= 6))
610 if (self->browser == WEUA_Mozilla)
615 - (BOOL)isTextModeBrowser {
616 if (self->browser == WEUA_Lynx) return YES;
617 if (self->browser == WEUA_Links) return YES;
618 if (self->browser == WEUA_Emacs) return YES;
622 - (BOOL)isIFrameBrowser {
623 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
626 /* as suggested in OGo bug #634 */
627 if ((self->browser == WEUA_Mozilla) && (self->browserMajorVersion >= 5))
634 if (self->browser == WEUA_Wget) return YES;
635 if (self->browser == WEUA_JavaSDK) return YES;
636 if (self->browser == WEUA_PythonURLLIB) return YES;
637 if (self->browser == WEUA_Google) return YES;
640 - (BOOL)isDAVClient {
641 if (self->browser == WEUA_WebFolder) return YES;
642 if (self->browser == WEUA_DAVFS) return YES;
643 if (self->browser == WEUA_MACOSX_DAVFS) return YES;
644 if (self->browser == WEUA_CADAVER) return YES;
645 if (self->browser == WEUA_GOLIVE) return YES;
646 if (self->browser == WEUA_AppleDAVAccess) return YES;
647 if (self->browser == WEUA_Evolution) return YES;
648 if (self->browser == WEUA_SOUP) return YES;
649 if (self->browser == WEUA_MSOutlook) return YES;
650 if (self->browser == WEUA_MSOutlookExpress) return YES;
651 if (self->browser == WEUA_GNOMEVFS) return YES;
652 if (self->browser == WEUA_ZideLook) return YES;
653 if (self->browser == WEUA_Entourage) return YES;
654 if (self->browser == WEUA_Morgul) return YES;
655 if (self->browser == WEUA_Goliath) return YES;
656 if (self->browser == WEUA_PerlHTTPDAV) return YES;
657 if (self->browser == WEUA_WebDrive) return YES;
658 if (self->browser == WEUA_Sunbird) return YES;
659 if (self->browser == WEUA_WDFS) return YES;
660 if (self->browser == WEUA_ZideOne_Outlook) return YES;
664 - (BOOL)isXmlRpcClient {
665 if (self->browser == WEUA_xmlrpclib_py) return YES;
666 if (self->browser == WEUA_KungLog) return YES;
667 if (self->browser == WEUA_Ecto) return YES;
668 if (self->browser == WEUA_PEAR_XMLRPC) return YES;
669 if (self->browser == WEUA_Cook_XMLRPCdotNET) return YES;
672 - (BOOL)isBLogClient {
673 if (self->browser == WEUA_KungLog) return YES;
674 if (self->browser == WEUA_Ecto) return YES;
677 - (BOOL)isRSSClient {
678 if (self->browser == WEUA_NetNewsWire) return YES;
679 if (self->browser == WEUA_NewsFire) return YES;
683 - (BOOL)doesSupportCSSOverflow {
684 if (![self isCSS1Browser])
686 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
692 - (BOOL)doesSupportDHTMLDragAndDrop {
693 if (![self isJavaScriptBrowser])
695 if (self->os != WEOS_WINDOWS)
697 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
702 - (BOOL)doesSupportXMLDataIslands {
703 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
708 - (BOOL)doesSupportUTF8Encoding {
709 if (self->flags.acceptUTF8)
710 /* explicit UTF-8 support signaled in HTTP header */
713 switch (self->browser) {
721 case WEUA_ZideOne_Outlook:
722 /* browser so new, that they always supported UTF-8 ... */
725 if (self->browserMajorVersion >= 5)
727 return NO; // TODO: find out, whether IE 4 gurantees UTF-8 support
735 - (BOOL)isInternetExplorer {
736 return self->browser == WEUA_IE ? YES : NO;
738 - (BOOL)isInternetExplorer5 {
739 return (self->browser == WEUA_IE) && (self->browserMajorVersion == 5)
744 return self->browser == WEUA_Netscape ? YES : NO;
746 - (BOOL)isNetscape6 {
747 return (self->browser == WEUA_Netscape) && (self->browserMajorVersion == 6)
752 return self->browser == WEUA_Lynx ? YES : NO;
755 return self->browser == WEUA_Opera ? YES : NO;
758 return self->browser == WEUA_Amaya ? YES : NO;
761 return self->browser == WEUA_Emacs ? YES : NO;
764 return self->browser == WEUA_Wget ? YES : NO;
766 - (BOOL)isWebFolder {
767 return self->browser == WEUA_WebFolder ? YES : NO;
770 return self->browser == WEUA_Mozilla ? YES : NO;
773 return self->browser == WEUA_OmniWeb ? YES : NO;
776 return self->browser == WEUA_iCab ? YES : NO;
778 - (BOOL)isKonqueror {
779 return self->browser == WEUA_Konqueror ? YES : NO;
782 return self->browser == WEUA_PEAR_XMLRPC ? YES : NO;
787 - (BOOL)isWindowsBrowser {
788 return self->os == WEOS_WINDOWS ? YES : NO;
790 - (BOOL)isLinuxBrowser {
791 return self->os == WEOS_LINUX ? YES : NO;
793 - (BOOL)isMacBrowser {
794 return self->os == WEOS_MACOS ? YES : NO;
796 - (BOOL)isSunOSBrowser {
797 return self->os == WEOS_SUNOS ? YES : NO;
799 - (BOOL)isUnixBrowser {
807 - (BOOL)isX11Browser {
808 if ([self isTextModeBrowser])
810 if (![self isUnixBrowser])
817 - (id)copyWithZone:(NSZone *)_zone {
818 return [self retain];
823 - (NSString *)description {
826 s = [NSMutableString stringWithFormat:@"<%@[0x%p]:",
827 NSStringFromClass([self class]), self];
829 //[s appendFormat:@" ua='%@'", self->userAgent];
830 [s appendFormat:@" type=%@ v%i.%i",
831 [self userAgentType],
832 self->browserMajorVersion, self->browserMinorVersion];
833 [s appendFormat:@" os=%@", [self os]];
834 [s appendFormat:@" cpu=%@", [self cpu]];
836 if ([self isFastTableBrowser]) [s appendString:@" fast-tbl"];
837 if ([self isCSS1Browser]) [s appendString:@" css1"];
838 if ([self isCSS2Browser]) [s appendString:@" css2"];
839 if ([self isXULBrowser]) [s appendString:@" xul"];
840 if ([self isTextModeBrowser]) [s appendString:@" text"];
841 if ([self isRobot]) [s appendString:@" robot"];
842 if ([self isJavaScriptBrowser]) [s appendString:@" js"];
843 if ([self isVBScriptBrowser]) [s appendString:@" vb"];
845 [s appendString:@">"];
849 @end /* WEClientCapabilities */
851 static NSString *ClientCapsCacheKey = @"WEClientCapabilities";
853 @implementation WORequest(ClientCapabilities)
855 - (WEClientCapabilities *)clientCapabilities {
857 WEClientCapabilities *ccaps;
858 NSMutableDictionary *md;
860 if ((ua = [self userInfo]) == nil) {
861 ccaps = [WEClientCapabilities alloc];
862 if ((ccaps = [ccaps initWithRequest:self]) == nil)
864 ccaps = [ccaps autorelease];
866 ua = [[NSDictionary alloc] initWithObjects:&ccaps
867 forKeys:&ClientCapsCacheKey
869 [self setUserInfo:ua];
874 if ((ccaps = [ua objectForKey:ClientCapsCacheKey]))
877 ccaps = [WEClientCapabilities alloc];
878 if ((ccaps = [ccaps initWithRequest:self]) == nil)
880 ccaps = [ccaps autorelease];
882 md = [ua mutableCopy];
883 [md setObject:ccaps forKey:ClientCapsCacheKey];
886 [self setUserInfo:ua];
891 @end /* WORequest(ClientCapabilities) */
893 static NSString *WEClientDetectorFormName = @"WEClientDetect";
895 @implementation JSClientCapabilityDetector
897 - (id)initWithName:(NSString *)_name
898 associations:(NSDictionary *)_config
899 template:(WOElement *)_c
901 if ((self = [super initWithName:_name associations:_config template:_c])) {
902 self->formName = OWGetProperty(_config, @"formName");
903 self->clientCaps = OWGetProperty(_config, @"clientCaps");
909 [self->formName release];
910 [self->clientCaps release];
914 - (NSString *)_formNameInContext:(WOContext *)_ctx {
916 return [self->formName stringValueInComponent:[_ctx component]];
920 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
921 if (![_ctx isInForm]) {
923 warnWithFormat:@"you must use %@ inside a form !",
924 NSStringFromClass([self class])];
928 if ([_ctx isRenderingDisabled]) return;
930 if (![[[_ctx request] clientCapabilities] isJavaScriptBrowser])
931 /* only works on JavaScript browsers ... */
934 [_response appendContentString:@"<input type='hidden' name='"];
935 [_response appendContentString:WEClientDetectorFormName];
936 [_response appendContentString:@"' value='browserConfig' />"];
938 [_response appendContentString:@"<script language='JavaScript'>\n"];
939 [_response appendContentString:@"<!-- hide\n"];
941 [_response appendContentString:@"// -->\n"];
942 [_response appendContentString:@"</script>"];
945 @end /* JSClientCapabilityDetector */
948 Netscape 4.76, Windows NT 4
949 'Mozilla/4.76 [en] (WinNT; U)'
951 Netscape 6, Windows NT 4
952 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m18) Gecko/20001108 Netscape6/6.0'
954 Netscape Navigator 3.01[de], MacOS 8.1
955 'Mozilla/3.01 [de]-C-MACOS8 (Macintosh; I; PPC)'
957 Netscape Communicator 4.51, SuSE Linux 6.1
958 'Mozilla/4.51 [en] (X11; I; Linux 2.2.13 i686)'
960 Mozilla M17, Windows NT 4
961 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m17) Gecko/20000807'
963 Internet Explorer 5.5, Windows NT 4
964 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)'
966 Internet Explorer 3.0.1, MacOS 8.1
967 'Mozilla/3.0 (compatible; MSIE 3.0.1; Mac_PowerPC; Mac OS8)'
969 Internet Explorer 5.0, MacOS 8.1
970 'Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)'
972 Internet Explorer 5.0, SPARC Solaris 2.6 (trex)
973 'Mozilla/4.0 (compatible; MSIE 5.0; SunOS 5.6 sun4u; X11)'
975 Konqueror/2.0, SuSE Linux 7.0
976 'Mozilla/5.0 (compatible; Konqueror/2.0; X11); Supports MD5-Digest; Supports gzip encoding'
978 Lynx, SuSE Linux 6.1 (marvin)
979 'Lynx/2.8rel.2 libwww-FM/2.14'
981 Lynx, SPARC Solaris 2.6 (trex)
982 'Lynx/2.7 libwww-FM/2.14'
984 Opera 4.02, Windows NT 4
985 'Mozilla/4.73 (Windows NT 4.0; U) Opera 4.02 [en]'
987 Opera 5.0, Windows NT 4
988 'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 5.0 [en]'
990 Amaya 4.0, Windows NT 4
991 'amaya/V4.0 libwww/5.3.1'
993 XEmacs, SuSE Linux 6.1
994 'Emacs-W3/4.0pre.39 URL/p4.0pre.39 (i686-pc-linux; X11)'
996 XEmacs, SuSE Linux 7.2
997 'Emacs-W3/4.0pre.46 URL/p4.0pre.46 (i386-suse-linux; X11)'
1002 Windows 'WebFolder' NT4
1003 'Microsoft Data Access Internet Publishing Provider Cache Manager'
1004 'Mozilla/2.0 (compatible; MS FrontPage 4.0)'
1007 Windows 98 IE 5 WebFolders
1008 'Microsoft Data Access Internet Publishing Provider DAV'
1011 'OmniWeb/3.0.2 OWF/1999C'
1013 Links, SuSE Linux 6.1 (marvin)
1014 'Links (0.95; Linux 2.2.13 i686)'
1020 fetch/1.0 Darwin/1.3.7 (Power Macintosh)
1022 MacOSX 10.1.1 DAV FS
1023 WebDAVFS/1.0 Darwin/5.1 (Power Macintosh)
1025 MacOSX 10.2.1 DAV FS
1026 WebDAVFS/1.2.1 (01218000) Darwin/6.1 (Power Macintosh)
1028 MacOSX 10.4.2 DAV FS
1029 WebDAVFS/1.4.1 (01418000) Darwin/8.6.0 (Power Macintosh)
1032 'cadaver/0.17.0 neon/0.12.0-dev'
1035 'GoLive/5. 0 [] (Windows 98; RATBERT)'
1038 - (very) small X11 web browser
1045 'Python-urllib/1.13'
1047 Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework
1050 Outlook 2000 on W2K with M$ Web Publishing Assistent
1051 'Microsoft HTTP Post (RFC1867)'
1053 CURL program (libcurl)
1054 'curl/7.9.8 (i686-suse-linux) libcurl 7.9.8 (OpenSSL 0.9.6g) (ipv6 enabled)'
1056 Evolution 1.0.8 with Exchange Connector (WebDAV)
1059 Outlook 2002 on W2K (HotMail HTTP access)
1060 'Microsoft-Outlook/10.0 (TmstmpExt)'
1062 Outlook Express 5.5 on W2K (HotMail HTTP access)
1063 'Outlook-Express/5.5 (MSIE 5.5; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
1065 Outlook Express 6.0 on W2K (HotMail HTTP access)
1066 'Outlook-Express/6.0 (MSIE 6.0; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
1068 Nautilus (GNOME Virtual Filesystem)
1071 Konqueror 3.0.3 (SuSE 8.1)
1072 - does not send a user-agent in webdav:// mode !
1075 'neon/0.23.5 NeonConnection 0.0'
1077 Safari v74 (MacOSX 10.2)
1078 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/74 (KHTML, like Gecko) Safari/74'
1079 - why does it say Mozilla/5.0 ??
1081 Evolution 1.4.0 with Exchange Connector 1.4.0 (SuSE 8.2)
1084 Mozilla Firebird 0.6 (MacOSX 10.2)
1085 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6'
1087 SOUP (Evo OGo Connector by Anders)
1090 Entourage/X (Entourage WebDAV 10.1.4, MacOSX)
1091 'Entourage/10.0 (Mac_PowerPC; DigExt; TmstmpExt)'
1093 Some unknown iCal.app
1096 NetNewsWire full version:
1097 'NetNewsWire/1.0.5 (Mac OS X; http://ranchero.com/netnewswire/)'
1099 NetNewsWire lite version:
1100 'NetNewsWire/1.0.3 (Mac OS X; Lite; http://ranchero.com/netnewswire/)'
1103 'xmlrpclib.py/1.0.0 (by www.pythonware.com)'
1105 Windows 2000 IE 6 WebFolders
1106 'Microsoft Data Access Internet Publishing Provider DAV 1.1'
1108 Morgul, Windows WebDAV client
1111 Apple iSync v122 / CoreFoundation Network
1114 Kung-Log (WebServicesCore)
1115 'Kung-Log/1.3 (Macintosh; U; PPC Mac OS X) WebServicesCore'
1117 Ecto (WebServicesCore)
1118 'ecto (Macintosh; U; PPC Mac OS X) WebServicesCore'
1124 'Goliath/1.0.1 (Macintosh-Carbon; PPC)'
1130 'Mediapartners-Google/2.1'
1132 WebFolders Win XP SP2
1133 'Microsoft-WebDAV-MiniRedir/5.1.2600'
1136 'Microsoft Office Protocol Discovery'
1139 'WebDrive 7.10.1475 DAV'
1141 Nokia N80, Opera 8 (352x416, 24b)
1142 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; Series 60/; 7439) Opera 8.60 [de]'
1143 'X-OS-Prefs: fw:352; fh:416; cd:24c; pl:3; pj:0; pa:1;pi:0;ps:0;'
1146 'User-Agent: Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413 (KHTML, like Gecko) Safari/413'
1148 Nokia N80, WAP Browser
1149 'User-Agent: NokiaN80-1/3.0 (3.0611.0.8) Series60/3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1'
1150 'x-wap-profile: "http://nds1.nds.nokia.com/uaprof/NN80-1r100.xml"'
1152 Sony/Ericsson T610 (128x160, 16b)
1153 'user-agent: SonyEricssonT610/R301 Profile/MIDP-1.0 Configuration/CLDC-1.0 UP.Link/6.3.0.0.0'
1154 'x-up-devcap-charset: US-ASCII,ISO-8859-1,UTF-8,ISO-10646-UCS-2'
1155 'x-up-devcap-iscolor: 1'
1156 'x-up-devcap-max-pdu: 10000'
1157 'x-up-devcap-screendepth: 16'
1158 'x-up-devcap-screenpixels: 128,160'
1159 'x-up-forwarded-for: 10.233.155.62'
1160 'x-up-subno: 981574289-60174629'
1161 'x-up-wtls-info: off'
1162 'x-wap-profile: "http://wap.sonyericsson.com/UAprof/T610R301.xml"'
1165 'wdfs/1.4.2 neon/0.26.4'