2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include <NGObjWeb/WEClientCapabilities.h>
23 #include <NGObjWeb/WOAssociation.h>
24 #include <NGObjWeb/WOContext.h>
25 #include <NGObjWeb/WOComponent.h>
26 #include <NGObjWeb/WOResponse.h>
30 #define WEUA_UNKNOWN 0
32 #define WEUA_Netscape 2
38 #define WEUA_WebFolder 8
39 #define WEUA_Mozilla 9
40 #define WEUA_OmniWeb 10
42 #define WEUA_Konqueror 12
45 #define WEUA_CADAVER 15
46 #define WEUA_GOLIVE 16
47 #define WEUA_MACOSX_DAVFS 17
49 #define WEUA_JavaSDK 19
50 #define WEUA_PythonURLLIB 20
51 #define WEUA_AppleDAVAccess 21
52 #define WEUA_MSWebPublisher 22
54 #define WEUA_Evolution 24
55 #define WEUA_MSOutlook 25
56 #define WEUA_MSOutlookExpress 26
57 #define WEUA_GNOMEVFS 27
58 #define WEUA_ZideLook 28
59 #define WEUA_Safari 29
61 #define WEUA_Entourage 31
62 #define WEUA_NetNewsWire 32
63 #define WEUA_xmlrpclib_py 33
64 #define WEUA_Morgul 34
65 #define WEUA_CFNetwork 35
66 #define WEUA_KungLog 36
69 #define WEUA_NewsFire 39
70 #define WEUA_Goliath 40
72 #define WEOS_UNKNOWN 0
73 #define WEOS_WINDOWS 1
78 #define WECPU_UNKNOWN 0
83 @interface WEClientCapabilities(Privates)
84 - (id)initWithRequest:(WORequest *)_request;
87 @implementation WEClientCapabilities
89 - (id)initWithRequest:(WORequest *)_request {
91 const unsigned char *ua;
92 const unsigned char *tmp;
93 int defaultOS = WEOS_UNKNOWN;
94 int defaultCPU = WECPU_UNKNOWN;
98 if ((ac = [_request headerForKey:@"accept-charset"])) {
99 /* not really correct ..., eg could have quality "0" ! */
100 ac = [ac lowercaseString];
101 if ([ac rangeOfString:@"utf-8"].length > 0)
102 self->flags.acceptUTF8 = 1;
105 /* process user-agent */
107 self->userAgent = [[_request headerForKey:@"user-agent"] copy];
108 ua = [self->userAgent cString];
110 /* no user-agent, eg telnet */
116 if ((tmp = strstr(ua, "Opera"))) {
117 /* Opera (can fake to be MSIE or Netscape) */
118 self->browser = WEUA_Opera;
120 /* go to next space */
121 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
123 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
125 self->browserMajorVersion = atoi(tmp);
126 if ((tmp = index(tmp, '.'))) {
128 self->browserMinorVersion = atoi(tmp);
131 else if (strstr(ua, "NeonConnection") != NULL ||
132 strstr(ua, "ZIDEStore") != NULL ||
133 strstr(ua, "ZideLook-Codeon") != NULL) {
134 self->browser = WEUA_ZideLook;
135 self->browserMinorVersion = 0;
136 self->browserMajorVersion = 0;
138 else if ((tmp = strstr(ua, "Safari/"))) {
139 /* Hm, Safari says it is a Mozilla/5.0 ? */
141 self->browser = WEUA_Safari;
142 tmp += 7; /* skip "Safari/" */
143 combinedVersion = atoi(tmp);
144 /* well, don't know how this is supposed to work? 100=v1.1 */
145 if (combinedVersion == 100 /* 100 is v1.1 */) {
146 self->browserMajorVersion = 1;
147 self->browserMinorVersion = 1;
150 /* watch for upcoming versions ... */
151 self->browserMajorVersion = combinedVersion / 100;
154 else if (strstr(ua, "Outlook-Express/")) {
155 /* Outlook Express 5.5 mailbox access via http */
156 self->browser = WEUA_MSOutlookExpress;
158 else if (strstr(ua, "Outlook Express/")) {
159 /* Outlook Express 5.0 mailbox access via http */
160 self->browser = WEUA_MSOutlookExpress;
162 else if (strstr(ua, "Microsoft-Outlook/")) {
163 /* Outlook 2002 mailbox access via http */
164 self->browser = WEUA_MSOutlook;
166 else if (strstr(ua, "Microsoft HTTP Post")) {
167 /* Outlook 2000 with WebPublishing Assistent */
168 self->browser = WEUA_MSWebPublisher;
170 else if (strstr(ua, "Entourage/10")) {
171 /* Entourage MacOSX 10.1.4 */
172 self->browser = WEUA_Entourage;
174 else if ((tmp = strstr(ua, "MSIE"))) {
175 /* Internet Explorer */
176 self->browser = WEUA_IE;
178 /* go to next space */
179 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
181 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
183 self->browserMajorVersion = atoi(tmp);
184 if ((tmp = index(tmp, '.'))) {
186 self->browserMinorVersion = atoi(tmp);
189 else if ((tmp = strstr(ua, "Konqueror"))) {
190 /* Konqueror (KDE2 FileManager) */
191 self->browser = WEUA_Konqueror;
193 if ((tmp = index(tmp, '/'))) {
195 self->browserMajorVersion = atoi(tmp);
196 if ((tmp = index(tmp, '.'))) {
198 self->browserMinorVersion = atoi(tmp);
202 else if ((tmp = strstr(ua, "Netscape6"))) {
204 self->browser = WEUA_Netscape;
206 if ((tmp = index(tmp, '/'))) {
208 self->browserMajorVersion = atoi(tmp);
209 if ((tmp = index(tmp, '.'))) {
211 self->browserMinorVersion = atoi(tmp);
215 else if (strstr(ua, "Lynx")) {
217 self->browser = WEUA_Lynx;
219 else if (strstr(ua, "Links")) {
221 self->browser = WEUA_Links;
223 else if (strstr(ua, "gnome-vfs")) {
225 self->browser = WEUA_GNOMEVFS;
227 else if (strstr(ua, "cadaver")) {
228 /* Cadaver DAV browser */
229 self->browser = WEUA_CADAVER;
231 else if (strstr(ua, "GoLive")) {
233 self->browser = WEUA_GOLIVE;
235 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "fetch/") != NULL) {
236 /* MacOSX 10.0 DAV FileSystem */
237 self->browser = WEUA_MACOSX_DAVFS;
239 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "WebDAVFS/") != NULL) {
240 /* MacOSX DAV FileSystem */
241 self->browser = WEUA_MACOSX_DAVFS;
243 else if (strstr(ua, "OmniWeb")) {
245 self->browser = WEUA_OmniWeb;
247 else if (strstr(ua, "Evolution")) {
249 self->browser = WEUA_Evolution;
251 else if (strstr(ua, "Soup/")) {
252 /* SOUP (GNOME WebDAV library) */
253 self->browser = WEUA_SOUP;
255 else if (strstr(ua, "amaya")) {
257 self->browser = WEUA_Amaya;
259 else if (strstr(ua, "NetNewsWire/")) {
261 self->browser = WEUA_NetNewsWire;
263 else if (strstr(ua, "Dillo")) {
265 self->browser = WEUA_Dillo;
267 else if (strstr(ua, "Java")) {
269 self->browser = WEUA_JavaSDK;
271 else if (strstr(ua, "Python-urllib")) {
272 /* Python URL module */
273 self->browser = WEUA_PythonURLLIB;
275 else if (strstr(ua, "xmlrpclib.py/")) {
276 /* Python XML-RPC module */
277 self->browser = WEUA_xmlrpclib_py;
279 else if (strstr(ua, "Emacs")) {
281 self->browser = WEUA_Emacs;
283 else if (strstr(ua, "iCab")) {
285 self->browser = WEUA_iCab;
287 else if (strstr(ua, "Wget")) {
289 self->browser = WEUA_Wget;
291 else if (strstr(ua, "DAVAccess")) {
292 /* Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework */
293 self->browser = WEUA_AppleDAVAccess;
295 else if (strstr(ua, "DAVKit/")) {
296 /* some iCal 1.x DAV Access Framework, report as Apple DAV access */
297 self->browser = WEUA_AppleDAVAccess;
299 else if (strstr(ua, "Microsoft Data Access Internet Publishing Provider")) {
301 self->browser = WEUA_WebFolder;
303 else if (strstr(ua, "curl")) {
305 self->browser = WEUA_CURL;
307 else if (strstr(ua, "Mozilla")) {
308 /* other Netscape browser */
309 if (strstr(ua, "Mozilla/5")) {
310 self->browser = WEUA_Mozilla;
311 self->browserMajorVersion = 5;
313 else if (strstr(ua, "Mozilla/4")) {
314 self->browser = WEUA_Netscape;
315 self->browserMajorVersion = 4;
318 NSLog(@"%s: Unknown Mozilla Browser: user-agent='%@'",
319 __PRETTY_FUNCTION__, self->userAgent);
322 else if (strstr(ua, "Morgul")) {
323 self->browser = WEUA_Morgul;
325 else if (strstr(ua, "CFNetwork/1.1")) {
326 self->browser = WEUA_CFNetwork;
328 else if (strstr(ua, "Kung-Log/")) {
329 self->browser = WEUA_KungLog;
331 else if (strstr(ua, "ecto")) {
332 self->browser = WEUA_Ecto;
334 else if (strstr(ua, "NewsFire")) {
335 self->browser = WEUA_NewsFire;
337 else if (strstr(ua, "Goliath")) {
338 self->browser = WEUA_Goliath;
340 else if (strstr(ua, "SOPE/")) {
341 self->browser = WEUA_SOPE;
344 /* unknown browser */
345 self->browser = WEUA_UNKNOWN;
347 if (self->userAgent) {
348 NSLog(@"%s: Unknown WebClient: user-agent='%@'",
349 __PRETTY_FUNCTION__, self->userAgent);
355 if (strstr(ua, "Windows") != NULL || strstr(ua, "WinNT") != NULL)
356 self->os = WEOS_WINDOWS;
357 else if (strstr(ua, "Linux"))
358 self->os = WEOS_LINUX;
359 else if (strstr(ua, "Mac"))
360 self->os = WEOS_MACOS;
361 else if (strstr(ua, "SunOS"))
362 self->os = WEOS_SUNOS;
364 self->os = defaultOS;
368 if (strstr(ua, "sun4u"))
369 self->cpu = WECPU_SPARC;
370 else if (strstr(ua, "i686") || strstr(ua, "i586"))
371 self->cpu = WECPU_IX86;
372 else if (strstr(ua, "PowerPC") || strstr(ua, "ppc") || strstr(ua, "PPC"))
373 self->cpu = WECPU_PPC;
374 else if (self->os == WEOS_WINDOWS)
375 /* assume ix86 if OS is Windows .. */
376 self->cpu = WECPU_IX86;
378 self->cpu = defaultCPU;
384 [self->userAgent release];
390 - (NSString *)userAgent {
391 return self->userAgent;
394 - (NSString *)userAgentType {
395 switch (self->browser) {
396 case WEUA_IE: return @"IE";
397 case WEUA_Netscape: return @"Netscape";
398 case WEUA_Lynx: return @"Lynx";
399 case WEUA_Links: return @"Links";
400 case WEUA_Opera: return @"Opera";
401 case WEUA_Amaya: return @"Amaya";
402 case WEUA_Emacs: return @"Emacs";
403 case WEUA_Wget: return @"Wget";
404 case WEUA_WebFolder: return @"WebFolder";
405 case WEUA_DAVFS: return @"DAVFS";
406 case WEUA_MACOSX_DAVFS: return @"MacOSXDAVFS";
407 case WEUA_CADAVER: return @"Cadaver";
408 case WEUA_GOLIVE: return @"GoLive";
409 case WEUA_Mozilla: return @"Mozilla";
410 case WEUA_OmniWeb: return @"OmniWeb";
411 case WEUA_iCab: return @"iCab";
412 case WEUA_Konqueror: return @"Konqueror";
413 case WEUA_Dillo: return @"Dillo";
414 case WEUA_JavaSDK: return @"Java";
415 case WEUA_PythonURLLIB: return @"Python-urllib";
416 case WEUA_AppleDAVAccess: return @"AppleDAVAccess";
417 case WEUA_MSWebPublisher: return @"MSWebPublisher";
418 case WEUA_CURL: return @"CURL";
419 case WEUA_Evolution: return @"Evolution";
420 case WEUA_SOUP: return @"SOUP";
421 case WEUA_MSOutlook: return @"MSOutlook";
422 case WEUA_MSOutlookExpress: return @"MSOutlookExpress";
423 case WEUA_GNOMEVFS: return @"GNOME-VFS";
424 case WEUA_ZideLook: return @"ZideLook";
425 case WEUA_Safari: return @"Safari";
426 case WEUA_Entourage: return @"Entourage";
427 case WEUA_NetNewsWire: return @"NetNewsWire";
428 case WEUA_xmlrpclib_py: return @"xmlrpclib.py";
429 case WEUA_Morgul: return @"Morgul";
430 case WEUA_KungLog: return @"KungLog";
431 case WEUA_Ecto: return @"Ecto";
432 case WEUA_NewsFire: return @"NewsFire";
433 case WEUA_Goliath: return @"Goliath";
434 default: return @"unknown";
439 case WEOS_WINDOWS: return @"Windows";
440 case WEOS_LINUX: return @"Linux";
441 case WEOS_MACOS: return @"MacOS";
442 case WEOS_SUNOS: return @"SunOS";
443 default: return @"unknown";
448 case WECPU_IX86: return @"ix86";
449 case WECPU_SPARC: return @"sparc";
450 case WECPU_PPC: return @"ppc";
451 default: return @"unknown";
455 - (unsigned char)majorVersion {
456 return self->browserMajorVersion;
458 - (unsigned char)minorVersion {
459 return self->browserMinorVersion;
462 /* browser capabilities */
464 - (BOOL)isJavaScriptBrowser {
465 switch (self->browser) {
478 - (BOOL)isVBScriptBrowser {
479 switch (self->browser) {
488 - (BOOL)isFastTableBrowser {
489 switch (self->browser) {
501 return (self->browserMajorVersion >= 6)
509 - (BOOL)isCSS2Browser {
510 switch (self->browser) {
511 case WEUA_IE: return (self->browserMajorVersion >= 5) ? YES : NO;
512 case WEUA_Netscape: return (self->browserMajorVersion >= 6) ? YES : NO;
513 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
514 case WEUA_Mozilla: return YES;
515 case WEUA_Safari: return YES;
516 case WEUA_Konqueror: return NO;
521 - (BOOL)isCSS1Browser {
522 switch (self->browser) {
523 case WEUA_IE: return (self->browserMajorVersion >= 4) ? YES : NO;
524 case WEUA_Netscape: return (self->browserMajorVersion >= 4) ? YES : NO;
525 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
526 case WEUA_Safari: return YES;
527 case WEUA_Konqueror: return NO;
532 - (BOOL)ignoresCSSOnFormElements {
533 if (self->browser == WEUA_Safari) /* Safari always displays Aqua buttons */
536 return [self isCSS1Browser] ? NO : YES;
539 - (BOOL)isXULBrowser {
540 if (self->browser == WEUA_Safari)
542 if ((self->browser == WEUA_Netscape) && (self->browserMajorVersion >= 6))
544 if (self->browser == WEUA_Mozilla)
549 - (BOOL)isTextModeBrowser {
550 if (self->browser == WEUA_Lynx) return YES;
551 if (self->browser == WEUA_Links) return YES;
552 if (self->browser == WEUA_Emacs) return YES;
556 - (BOOL)isIFrameBrowser {
557 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
560 /* as suggested in OGo bug #634 */
561 if ((self->browser == WEUA_Mozilla) && (self->browserMajorVersion >= 5))
568 if (self->browser == WEUA_Wget) return YES;
569 if (self->browser == WEUA_JavaSDK) return YES;
570 if (self->browser == WEUA_PythonURLLIB) return YES;
573 - (BOOL)isDAVClient {
574 if (self->browser == WEUA_WebFolder) return YES;
575 if (self->browser == WEUA_DAVFS) return YES;
576 if (self->browser == WEUA_MACOSX_DAVFS) return YES;
577 if (self->browser == WEUA_CADAVER) return YES;
578 if (self->browser == WEUA_GOLIVE) return YES;
579 if (self->browser == WEUA_AppleDAVAccess) return YES;
580 if (self->browser == WEUA_Evolution) return YES;
581 if (self->browser == WEUA_SOUP) return YES;
582 if (self->browser == WEUA_MSOutlook) return YES;
583 if (self->browser == WEUA_MSOutlookExpress) return YES;
584 if (self->browser == WEUA_GNOMEVFS) return YES;
585 if (self->browser == WEUA_ZideLook) return YES;
586 if (self->browser == WEUA_Entourage) return YES;
587 if (self->browser == WEUA_Morgul) return YES;
588 if (self->browser == WEUA_Goliath) return YES;
592 - (BOOL)isXmlRpcClient {
593 if (self->browser == WEUA_xmlrpclib_py) return YES;
594 if (self->browser == WEUA_KungLog) return YES;
595 if (self->browser == WEUA_Ecto) return YES;
598 - (BOOL)isBLogClient {
599 if (self->browser == WEUA_KungLog) return YES;
600 if (self->browser == WEUA_Ecto) return YES;
603 - (BOOL)isRSSClient {
604 if (self->browser == WEUA_NetNewsWire) return YES;
605 if (self->browser == WEUA_NewsFire) return YES;
609 - (BOOL)doesSupportCSSOverflow {
610 if (![self isCSS1Browser])
612 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
618 - (BOOL)doesSupportDHTMLDragAndDrop {
619 if (![self isJavaScriptBrowser])
621 if (self->os != WEOS_WINDOWS)
623 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
628 - (BOOL)doesSupportXMLDataIslands {
629 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
634 - (BOOL)doesSupportUTF8Encoding {
635 if (self->flags.acceptUTF8)
636 /* explicit UTF-8 support signaled in HTTP header */
639 switch (self->browser) {
646 /* browser so new, that they always supported UTF-8 ... */
649 if (self->browserMajorVersion >= 5)
651 return NO; // TODO: find out, whether IE 4 gurantees UTF-8 support
659 - (BOOL)isInternetExplorer {
660 return self->browser == WEUA_IE ? YES : NO;
662 - (BOOL)isInternetExplorer5 {
663 return (self->browser == WEUA_IE) && (self->browserMajorVersion == 5)
668 return self->browser == WEUA_Netscape ? YES : NO;
670 - (BOOL)isNetscape6 {
671 return (self->browser == WEUA_Netscape) && (self->browserMajorVersion == 6)
676 return self->browser == WEUA_Lynx ? YES : NO;
679 return self->browser == WEUA_Opera ? YES : NO;
682 return self->browser == WEUA_Amaya ? YES : NO;
685 return self->browser == WEUA_Emacs ? YES : NO;
688 return self->browser == WEUA_Wget ? YES : NO;
690 - (BOOL)isWebFolder {
691 return self->browser == WEUA_WebFolder ? YES : NO;
694 return self->browser == WEUA_Mozilla ? YES : NO;
697 return self->browser == WEUA_OmniWeb ? YES : NO;
700 return self->browser == WEUA_iCab ? YES : NO;
702 - (BOOL)isKonqueror {
703 return self->browser == WEUA_Konqueror ? YES : NO;
708 - (BOOL)isWindowsBrowser {
709 return self->os == WEOS_WINDOWS ? YES : NO;
711 - (BOOL)isLinuxBrowser {
712 return self->os == WEOS_LINUX ? YES : NO;
714 - (BOOL)isMacBrowser {
715 return self->os == WEOS_MACOS ? YES : NO;
717 - (BOOL)isSunOSBrowser {
718 return self->os == WEOS_SUNOS ? YES : NO;
720 - (BOOL)isUnixBrowser {
728 - (BOOL)isX11Browser {
729 if ([self isTextModeBrowser])
731 if (![self isUnixBrowser])
738 - (id)copyWithZone:(NSZone *)_zone {
739 return [self retain];
744 - (NSString *)description {
747 s = [NSMutableString stringWithFormat:@"<%@[0x%08X]:",
748 NSStringFromClass([self class]), self];
750 //[s appendFormat:@" ua='%@'", self->userAgent];
751 [s appendFormat:@" type=%@ v%i.%i>",
752 [self userAgentType],
753 self->browserMajorVersion, self->browserMinorVersion];
754 [s appendFormat:@" os=%@", [self os]];
755 [s appendFormat:@" cpu=%@", [self cpu]];
757 if ([self isFastTableBrowser]) [s appendString:@" fast-tbl"];
758 if ([self isCSS1Browser]) [s appendString:@" css1"];
759 if ([self isCSS2Browser]) [s appendString:@" css2"];
760 if ([self isXULBrowser]) [s appendString:@" xul"];
761 if ([self isTextModeBrowser]) [s appendString:@" text"];
762 if ([self isRobot]) [s appendString:@" robot"];
763 if ([self isJavaScriptBrowser]) [s appendString:@" js"];
764 if ([self isVBScriptBrowser]) [s appendString:@" vb"];
766 [s appendString:@">"];
770 @end /* WEClientCapabilities */
772 static NSString *ClientCapsCacheKey = @"WEClientCapabilties";
774 @implementation WORequest(ClientCapabilities)
776 - (WEClientCapabilities *)clientCapabilities {
778 WEClientCapabilities *ccaps;
779 NSMutableDictionary *md;
781 if ((ua = [self userInfo]) == nil) {
782 ccaps = [WEClientCapabilities alloc];
783 if ((ccaps = [ccaps initWithRequest:self]) == nil)
785 ccaps = [ccaps autorelease];
787 ua = [[NSDictionary alloc] initWithObjects:&ccaps
788 forKeys:&ClientCapsCacheKey
790 [self setUserInfo:ua];
795 if ((ccaps = [ua objectForKey:ClientCapsCacheKey]))
798 ccaps = [WEClientCapabilities alloc];
799 if ((ccaps = [ccaps initWithRequest:self]) == nil)
801 ccaps = [ccaps autorelease];
803 md = [ua mutableCopy];
804 [md setObject:ccaps forKey:ClientCapsCacheKey];
807 [self setUserInfo:ua];
812 @end /* WORequest(ClientCapabilities) */
814 static NSString *WEClientDetectorFormName = @"WEClientDetect";
816 @implementation JSClientCapabilityDetector
818 - (id)initWithName:(NSString *)_name
819 associations:(NSDictionary *)_config
820 template:(WOElement *)_c
822 if ((self = [super initWithName:_name associations:_config template:_c])) {
823 self->formName = OWGetProperty(_config, @"formName");
824 self->clientCaps = OWGetProperty(_config, @"clientCaps");
830 [self->formName release];
831 [self->clientCaps release];
835 - (NSString *)_formNameInContext:(WOContext *)_ctx {
837 return [self->formName stringValueInComponent:[_ctx component]];
841 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
842 if (![_ctx isInForm]) {
844 logWithFormat:@"WARNING: you must use %@ inside a form !",
845 NSStringFromClass([self class])];
849 if (![[[_ctx request] clientCapabilities] isJavaScriptBrowser])
850 /* only works on JavaScript browsers ... */
853 [_response appendContentString:@"<input type='hidden' name='"];
854 [_response appendContentString:WEClientDetectorFormName];
855 [_response appendContentString:@"' value='browserConfig' />"];
857 [_response appendContentString:@"<script language='JavaScript'>\n"];
858 [_response appendContentString:@"<!-- hide\n"];
860 [_response appendContentString:@"// -->\n"];
861 [_response appendContentString:@"</script>"];
864 @end /* JSClientCapabilityDetector */
867 Netscape 4.76, Windows NT 4
868 'Mozilla/4.76 [en] (WinNT; U)'
870 Netscape 6, Windows NT 4
871 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m18) Gecko/20001108 Netscape6/6.0'
873 Netscape Navigator 3.01[de], MacOS 8.1
874 'Mozilla/3.01 [de]-C-MACOS8 (Macintosh; I; PPC)'
876 Netscape Communicator 4.51, SuSE Linux 6.1
877 'Mozilla/4.51 [en] (X11; I; Linux 2.2.13 i686)'
879 Mozilla M17, Windows NT 4
880 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m17) Gecko/20000807'
882 Internet Explorer 5.5, Windows NT 4
883 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)'
885 Internet Explorer 3.0.1, MacOS 8.1
886 'Mozilla/3.0 (compatible; MSIE 3.0.1; Mac_PowerPC; Mac OS8)'
888 Internet Explorer 5.0, MacOS 8.1
889 'Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)'
891 Internet Explorer 5.0, SPARC Solaris 2.6 (trex)
892 'Mozilla/4.0 (compatible; MSIE 5.0; SunOS 5.6 sun4u; X11)'
894 Konqueror/2.0, SuSE Linux 7.0
895 'Mozilla/5.0 (compatible; Konqueror/2.0; X11); Supports MD5-Digest; Supports gzip encoding'
897 Lynx, SuSE Linux 6.1 (marvin)
898 'Lynx/2.8rel.2 libwww-FM/2.14'
900 Lynx, SPARC Solaris 2.6 (trex)
901 'Lynx/2.7 libwww-FM/2.14'
903 Opera 4.02, Windows NT 4
904 'Mozilla/4.73 (Windows NT 4.0; U) Opera 4.02 [en]'
906 Opera 5.0, Windows NT 4
907 'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 5.0 [en]'
909 Amaya 4.0, Windows NT 4
910 'amaya/V4.0 libwww/5.3.1'
912 XEmacs, SuSE Linux 6.1
913 'Emacs-W3/4.0pre.39 URL/p4.0pre.39 (i686-pc-linux; X11)'
915 XEmacs, SuSE Linux 7.2
916 'Emacs-W3/4.0pre.46 URL/p4.0pre.46 (i386-suse-linux; X11)'
921 Windows 'WebFolder' NT4
922 'Microsoft Data Access Internet Publishing Provider Cache Manager'
923 'Mozilla/2.0 (compatible; MS FrontPage 4.0)'
926 Windows 98 IE 5 WebFolders
927 'Microsoft Data Access Internet Publishing Provider DAV'
930 'OmniWeb/3.0.2 OWF/1999C'
932 Links, SuSE Linux 6.1 (marvin)
933 'Links (0.95; Linux 2.2.13 i686)'
939 fetch/1.0 Darwin/1.3.7 (Power Macintosh)
942 WebDAVFS/1.0 Darwin/5.1 (Power Macintosh)
945 WebDAVFS/1.2.1 (01218000) Darwin/6.1 (Power Macintosh)
948 'cadaver/0.17.0 neon/0.12.0-dev'
951 'GoLive/5. 0 [] (Windows 98; RATBERT)'
954 - (very) small X11 web browser
963 Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework
966 Outlook 2000 on W2K with M$ Web Publishing Assistent
967 'Microsoft HTTP Post (RFC1867)'
969 CURL program (libcurl)
970 'curl/7.9.8 (i686-suse-linux) libcurl 7.9.8 (OpenSSL 0.9.6g) (ipv6 enabled)'
972 Evolution 1.0.8 with Exchange Connector (WebDAV)
975 Outlook 2002 on W2K (HotMail HTTP access)
976 'Microsoft-Outlook/10.0 (TmstmpExt)'
978 Outlook Express 5.5 on W2K (HotMail HTTP access)
979 'Outlook-Express/5.5 (MSIE 5.5; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
981 Outlook Express 6.0 on W2K (HotMail HTTP access)
982 'Outlook-Express/6.0 (MSIE 6.0; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
984 Nautilus (GNOME Virtual Filesystem)
987 Konqueror 3.0.3 (SuSE 8.1)
988 - does not send a user-agent in webdav:// mode !
991 'neon/0.23.5 NeonConnection 0.0'
993 Safari v74 (MacOSX 10.2)
994 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/74 (KHTML, like Gecko) Safari/74'
995 - why does it say Mozilla/5.0 ??
997 Evolution 1.4.0 with Exchange Connector 1.4.0 (SuSE 8.2)
1000 Mozilla Firebird 0.6 (MacOSX 10.2)
1001 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6'
1003 SOUP (Evo OGo Connector by Anders)
1006 Entourage/X (Entourage WebDAV 10.1.4, MacOSX)
1007 'Entourage/10.0 (Mac_PowerPC; DigExt; TmstmpExt)'
1009 Some unknown iCal.app
1012 NetNewsWire full version:
1013 'NetNewsWire/1.0.5 (Mac OS X; http://ranchero.com/netnewswire/)'
1015 NetNewsWire lite version:
1016 'NetNewsWire/1.0.3 (Mac OS X; Lite; http://ranchero.com/netnewswire/)'
1019 'xmlrpclib.py/1.0.0 (by www.pythonware.com)'
1021 Windows 2000 IE 6 WebFolders
1022 'Microsoft Data Access Internet Publishing Provider DAV 1.1'
1024 Morgul, Windows WebDAV client
1027 Apple iSync v122 / CoreFoundation Network
1030 Kung-Log (WebServicesCore)
1031 'Kung-Log/1.3 (Macintosh; U; PPC Mac OS X) WebServicesCore'
1033 Ecto (WebServicesCore)
1034 'ecto (Macintosh; U; PPC Mac OS X) WebServicesCore'
1040 'Goliath/1.0.1 (Macintosh-Carbon; PPC)'