2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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 SOPE 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 SOPE; 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
71 #define WEUA_PerlHTTPDAV 41
72 #define WEUA_Google 42
74 #define WEOS_UNKNOWN 0
75 #define WEOS_WINDOWS 1
80 #define WECPU_UNKNOWN 0
85 @interface WEClientCapabilities(Privates)
86 - (id)initWithRequest:(WORequest *)_request;
89 @implementation WEClientCapabilities
91 - (id)initWithRequest:(WORequest *)_request {
95 int defaultOS = WEOS_UNKNOWN;
96 int defaultCPU = WECPU_UNKNOWN;
100 if ((ac = [_request headerForKey:@"accept-charset"])) {
101 /* not really correct ..., eg could have quality "0" ! */
102 ac = [ac lowercaseString];
103 if ([ac rangeOfString:@"utf-8"].length > 0)
104 self->flags.acceptUTF8 = 1;
107 /* process user-agent */
109 self->userAgent = [[_request headerForKey:@"user-agent"] copy];
110 ua = [self->userAgent cString];
112 /* no user-agent, eg telnet */
118 if ((tmp = strstr(ua, "Opera"))) {
119 /* Opera (can fake to be MSIE or Netscape) */
120 self->browser = WEUA_Opera;
122 /* go to next space */
123 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
125 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
127 self->browserMajorVersion = atoi(tmp);
128 if ((tmp = index(tmp, '.'))) {
130 self->browserMinorVersion = atoi(tmp);
133 else if (strstr(ua, "NeonConnection") != NULL ||
134 strstr(ua, "ZIDEStore") != NULL ||
135 strstr(ua, "ZideLook-Codeon") != NULL) {
136 self->browser = WEUA_ZideLook;
137 self->browserMinorVersion = 0;
138 self->browserMajorVersion = 0;
140 else if ((tmp = strstr(ua, "Safari/"))) {
141 /* Hm, Safari says it is a Mozilla/5.0 ? */
143 self->browser = WEUA_Safari;
144 tmp += 7; /* skip "Safari/" */
145 combinedVersion = atoi(tmp);
146 /* well, don't know how this is supposed to work? 100=v1.1 */
147 if (combinedVersion == 100 /* 100 is v1.1 */) {
148 self->browserMajorVersion = 1;
149 self->browserMinorVersion = 1;
152 /* watch for upcoming versions ... */
153 self->browserMajorVersion = combinedVersion / 100;
156 else if (strstr(ua, "Outlook-Express/")) {
157 /* Outlook Express 5.5 mailbox access via http */
158 self->browser = WEUA_MSOutlookExpress;
160 else if (strstr(ua, "Outlook Express/")) {
161 /* Outlook Express 5.0 mailbox access via http */
162 self->browser = WEUA_MSOutlookExpress;
164 else if (strstr(ua, "Microsoft-Outlook/")) {
165 /* Outlook 2002 mailbox access via http */
166 self->browser = WEUA_MSOutlook;
168 else if (strstr(ua, "Microsoft HTTP Post")) {
169 /* Outlook 2000 with WebPublishing Assistent */
170 self->browser = WEUA_MSWebPublisher;
172 else if (strstr(ua, "Entourage/10")) {
173 /* Entourage MacOSX 10.1.4 */
174 self->browser = WEUA_Entourage;
176 else if ((tmp = strstr(ua, "MSIE"))) {
177 /* Internet Explorer */
178 self->browser = WEUA_IE;
180 /* go to next space */
181 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
183 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
185 self->browserMajorVersion = atoi(tmp);
186 if ((tmp = index(tmp, '.'))) {
188 self->browserMinorVersion = atoi(tmp);
191 else if ((tmp = strstr(ua, "Konqueror"))) {
192 /* Konqueror (KDE2 FileManager) */
193 self->browser = WEUA_Konqueror;
195 if ((tmp = index(tmp, '/'))) {
197 self->browserMajorVersion = atoi(tmp);
198 if ((tmp = index(tmp, '.'))) {
200 self->browserMinorVersion = atoi(tmp);
204 else if ((tmp = strstr(ua, "Netscape6"))) {
206 self->browser = WEUA_Netscape;
208 if ((tmp = index(tmp, '/'))) {
210 self->browserMajorVersion = atoi(tmp);
211 if ((tmp = index(tmp, '.'))) {
213 self->browserMinorVersion = atoi(tmp);
217 else if (strstr(ua, "Lynx")) {
219 self->browser = WEUA_Lynx;
221 else if (strstr(ua, "Links")) {
223 self->browser = WEUA_Links;
225 else if (strstr(ua, "gnome-vfs")) {
227 self->browser = WEUA_GNOMEVFS;
229 else if (strstr(ua, "cadaver")) {
230 /* Cadaver DAV browser */
231 self->browser = WEUA_CADAVER;
233 else if (strstr(ua, "GoLive")) {
235 self->browser = WEUA_GOLIVE;
237 else if (strstr(ua, "DAV.pm")) {
239 self->browser = WEUA_PerlHTTPDAV;
241 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "fetch/") != NULL) {
242 /* MacOSX 10.0 DAV FileSystem */
243 self->browser = WEUA_MACOSX_DAVFS;
245 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "WebDAVFS/") != NULL) {
246 /* MacOSX DAV FileSystem */
247 self->browser = WEUA_MACOSX_DAVFS;
249 else if (strstr(ua, "OmniWeb")) {
251 self->browser = WEUA_OmniWeb;
253 else if (strstr(ua, "Evolution")) {
255 self->browser = WEUA_Evolution;
257 else if (strstr(ua, "Soup/")) {
258 /* SOUP (GNOME WebDAV library) */
259 self->browser = WEUA_SOUP;
261 else if (strstr(ua, "amaya")) {
263 self->browser = WEUA_Amaya;
265 else if (strstr(ua, "NetNewsWire/")) {
267 self->browser = WEUA_NetNewsWire;
269 else if (strstr(ua, "Dillo")) {
271 self->browser = WEUA_Dillo;
273 else if (strstr(ua, "Java")) {
275 self->browser = WEUA_JavaSDK;
277 else if (strstr(ua, "Python-urllib")) {
278 /* Python URL module */
279 self->browser = WEUA_PythonURLLIB;
281 else if (strstr(ua, "xmlrpclib.py/")) {
282 /* Python XML-RPC module */
283 self->browser = WEUA_xmlrpclib_py;
285 else if (strstr(ua, "Emacs")) {
287 self->browser = WEUA_Emacs;
289 else if (strstr(ua, "iCab")) {
291 self->browser = WEUA_iCab;
293 else if (strstr(ua, "Wget")) {
295 self->browser = WEUA_Wget;
297 else if (strstr(ua, "DAVAccess")) {
298 /* Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework */
299 self->browser = WEUA_AppleDAVAccess;
301 else if (strstr(ua, "DAVKit/")) {
302 /* some iCal 1.x DAV Access Framework, report as Apple DAV access */
303 self->browser = WEUA_AppleDAVAccess;
305 else if (strstr(ua, "Microsoft Data Access Internet Publishing Provider")) {
307 self->browser = WEUA_WebFolder;
309 else if (strstr(ua, "curl")) {
311 self->browser = WEUA_CURL;
313 else if (strstr(ua, "Mozilla")) {
314 /* other Netscape browser */
315 if (strstr(ua, "Mozilla/5")) {
316 self->browser = WEUA_Mozilla;
317 self->browserMajorVersion = 5;
319 else if (strstr(ua, "Mozilla/4")) {
320 self->browser = WEUA_Netscape;
321 self->browserMajorVersion = 4;
324 NSLog(@"%s: Unknown Mozilla Browser: user-agent='%@'",
325 __PRETTY_FUNCTION__, self->userAgent);
328 else if (strstr(ua, "Morgul")) {
329 self->browser = WEUA_Morgul;
331 else if (strstr(ua, "CFNetwork/1.1")) {
332 self->browser = WEUA_CFNetwork;
334 else if (strstr(ua, "Kung-Log/")) {
335 self->browser = WEUA_KungLog;
337 else if (strstr(ua, "ecto")) {
338 self->browser = WEUA_Ecto;
340 else if (strstr(ua, "NewsFire")) {
341 self->browser = WEUA_NewsFire;
343 else if (strstr(ua, "Goliath")) {
344 self->browser = WEUA_Goliath;
346 else if (strstr(ua, "SOPE/")) {
347 self->browser = WEUA_SOPE;
349 else if (strstr(ua, "Mediapartners-Google/")) {
350 self->browser = WEUA_Google;
353 /* unknown browser */
354 self->browser = WEUA_UNKNOWN;
356 if (self->userAgent) {
357 NSLog(@"%s: Unknown WebClient: user-agent='%@'",
358 __PRETTY_FUNCTION__, self->userAgent);
364 if (strstr(ua, "Windows") != NULL || strstr(ua, "WinNT") != NULL)
365 self->os = WEOS_WINDOWS;
366 else if (strstr(ua, "Linux"))
367 self->os = WEOS_LINUX;
368 else if (strstr(ua, "Mac"))
369 self->os = WEOS_MACOS;
370 else if (strstr(ua, "SunOS"))
371 self->os = WEOS_SUNOS;
373 self->os = defaultOS;
377 if (strstr(ua, "sun4u"))
378 self->cpu = WECPU_SPARC;
379 else if (strstr(ua, "i686") || strstr(ua, "i586"))
380 self->cpu = WECPU_IX86;
381 else if (strstr(ua, "PowerPC") || strstr(ua, "ppc") || strstr(ua, "PPC"))
382 self->cpu = WECPU_PPC;
383 else if (self->os == WEOS_WINDOWS)
384 /* assume ix86 if OS is Windows .. */
385 self->cpu = WECPU_IX86;
387 self->cpu = defaultCPU;
393 [self->userAgent release];
399 - (NSString *)userAgent {
400 return self->userAgent;
403 - (NSString *)userAgentType {
404 switch (self->browser) {
405 case WEUA_IE: return @"IE";
406 case WEUA_Netscape: return @"Netscape";
407 case WEUA_Lynx: return @"Lynx";
408 case WEUA_Links: return @"Links";
409 case WEUA_Opera: return @"Opera";
410 case WEUA_Amaya: return @"Amaya";
411 case WEUA_Emacs: return @"Emacs";
412 case WEUA_Wget: return @"Wget";
413 case WEUA_WebFolder: return @"WebFolder";
414 case WEUA_DAVFS: return @"DAVFS";
415 case WEUA_MACOSX_DAVFS: return @"MacOSXDAVFS";
416 case WEUA_CADAVER: return @"Cadaver";
417 case WEUA_GOLIVE: return @"GoLive";
418 case WEUA_Mozilla: return @"Mozilla";
419 case WEUA_OmniWeb: return @"OmniWeb";
420 case WEUA_iCab: return @"iCab";
421 case WEUA_Konqueror: return @"Konqueror";
422 case WEUA_Dillo: return @"Dillo";
423 case WEUA_JavaSDK: return @"Java";
424 case WEUA_PythonURLLIB: return @"Python-urllib";
425 case WEUA_AppleDAVAccess: return @"AppleDAVAccess";
426 case WEUA_MSWebPublisher: return @"MSWebPublisher";
427 case WEUA_CURL: return @"CURL";
428 case WEUA_Evolution: return @"Evolution";
429 case WEUA_SOUP: return @"SOUP";
430 case WEUA_MSOutlook: return @"MSOutlook";
431 case WEUA_MSOutlookExpress: return @"MSOutlookExpress";
432 case WEUA_GNOMEVFS: return @"GNOME-VFS";
433 case WEUA_ZideLook: return @"ZideLook";
434 case WEUA_Safari: return @"Safari";
435 case WEUA_Entourage: return @"Entourage";
436 case WEUA_NetNewsWire: return @"NetNewsWire";
437 case WEUA_xmlrpclib_py: return @"xmlrpclib.py";
438 case WEUA_Morgul: return @"Morgul";
439 case WEUA_KungLog: return @"KungLog";
440 case WEUA_Ecto: return @"Ecto";
441 case WEUA_NewsFire: return @"NewsFire";
442 case WEUA_Goliath: return @"Goliath";
443 case WEUA_PerlHTTPDAV: return @"PerlHTTPDAV";
444 case WEUA_Google: return @"Google";
445 default: return @"unknown";
450 case WEOS_WINDOWS: return @"Windows";
451 case WEOS_LINUX: return @"Linux";
452 case WEOS_MACOS: return @"MacOS";
453 case WEOS_SUNOS: return @"SunOS";
454 default: return @"unknown";
459 case WECPU_IX86: return @"ix86";
460 case WECPU_SPARC: return @"sparc";
461 case WECPU_PPC: return @"ppc";
462 default: return @"unknown";
466 - (unsigned char)majorVersion {
467 return self->browserMajorVersion;
469 - (unsigned char)minorVersion {
470 return self->browserMinorVersion;
473 /* browser capabilities */
475 - (BOOL)isJavaScriptBrowser {
476 switch (self->browser) {
489 - (BOOL)isVBScriptBrowser {
490 switch (self->browser) {
499 - (BOOL)isFastTableBrowser {
500 switch (self->browser) {
512 return (self->browserMajorVersion >= 6)
520 - (BOOL)isCSS2Browser {
521 switch (self->browser) {
522 case WEUA_IE: return (self->browserMajorVersion >= 5) ? YES : NO;
523 case WEUA_Netscape: return (self->browserMajorVersion >= 6) ? YES : NO;
524 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
525 case WEUA_Mozilla: return YES;
526 case WEUA_Safari: return YES;
527 case WEUA_Konqueror: return NO;
532 - (BOOL)isCSS1Browser {
533 switch (self->browser) {
534 case WEUA_IE: return (self->browserMajorVersion >= 4) ? YES : NO;
535 case WEUA_Netscape: return (self->browserMajorVersion >= 4) ? YES : NO;
536 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
537 case WEUA_Safari: return YES;
538 case WEUA_Konqueror: return NO;
543 - (BOOL)ignoresCSSOnFormElements {
544 if (self->browser == WEUA_Safari) /* Safari always displays Aqua buttons */
547 return [self isCSS1Browser] ? NO : YES;
550 - (BOOL)isXULBrowser {
551 if (self->browser == WEUA_Safari) // TODO: Safari supports some XUL stuff
553 if ((self->browser == WEUA_Netscape) && (self->browserMajorVersion >= 6))
555 if (self->browser == WEUA_Mozilla)
560 - (BOOL)isTextModeBrowser {
561 if (self->browser == WEUA_Lynx) return YES;
562 if (self->browser == WEUA_Links) return YES;
563 if (self->browser == WEUA_Emacs) return YES;
567 - (BOOL)isIFrameBrowser {
568 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
571 /* as suggested in OGo bug #634 */
572 if ((self->browser == WEUA_Mozilla) && (self->browserMajorVersion >= 5))
579 if (self->browser == WEUA_Wget) return YES;
580 if (self->browser == WEUA_JavaSDK) return YES;
581 if (self->browser == WEUA_PythonURLLIB) return YES;
582 if (self->browser == WEUA_Google) return YES;
585 - (BOOL)isDAVClient {
586 if (self->browser == WEUA_WebFolder) return YES;
587 if (self->browser == WEUA_DAVFS) return YES;
588 if (self->browser == WEUA_MACOSX_DAVFS) return YES;
589 if (self->browser == WEUA_CADAVER) return YES;
590 if (self->browser == WEUA_GOLIVE) return YES;
591 if (self->browser == WEUA_AppleDAVAccess) return YES;
592 if (self->browser == WEUA_Evolution) return YES;
593 if (self->browser == WEUA_SOUP) return YES;
594 if (self->browser == WEUA_MSOutlook) return YES;
595 if (self->browser == WEUA_MSOutlookExpress) return YES;
596 if (self->browser == WEUA_GNOMEVFS) return YES;
597 if (self->browser == WEUA_ZideLook) return YES;
598 if (self->browser == WEUA_Entourage) return YES;
599 if (self->browser == WEUA_Morgul) return YES;
600 if (self->browser == WEUA_Goliath) return YES;
601 if (self->browser == WEUA_PerlHTTPDAV) return YES;
605 - (BOOL)isXmlRpcClient {
606 if (self->browser == WEUA_xmlrpclib_py) return YES;
607 if (self->browser == WEUA_KungLog) return YES;
608 if (self->browser == WEUA_Ecto) return YES;
611 - (BOOL)isBLogClient {
612 if (self->browser == WEUA_KungLog) return YES;
613 if (self->browser == WEUA_Ecto) return YES;
616 - (BOOL)isRSSClient {
617 if (self->browser == WEUA_NetNewsWire) return YES;
618 if (self->browser == WEUA_NewsFire) return YES;
622 - (BOOL)doesSupportCSSOverflow {
623 if (![self isCSS1Browser])
625 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
631 - (BOOL)doesSupportDHTMLDragAndDrop {
632 if (![self isJavaScriptBrowser])
634 if (self->os != WEOS_WINDOWS)
636 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
641 - (BOOL)doesSupportXMLDataIslands {
642 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
647 - (BOOL)doesSupportUTF8Encoding {
648 if (self->flags.acceptUTF8)
649 /* explicit UTF-8 support signaled in HTTP header */
652 switch (self->browser) {
659 /* browser so new, that they always supported UTF-8 ... */
662 if (self->browserMajorVersion >= 5)
664 return NO; // TODO: find out, whether IE 4 gurantees UTF-8 support
672 - (BOOL)isInternetExplorer {
673 return self->browser == WEUA_IE ? YES : NO;
675 - (BOOL)isInternetExplorer5 {
676 return (self->browser == WEUA_IE) && (self->browserMajorVersion == 5)
681 return self->browser == WEUA_Netscape ? YES : NO;
683 - (BOOL)isNetscape6 {
684 return (self->browser == WEUA_Netscape) && (self->browserMajorVersion == 6)
689 return self->browser == WEUA_Lynx ? YES : NO;
692 return self->browser == WEUA_Opera ? YES : NO;
695 return self->browser == WEUA_Amaya ? YES : NO;
698 return self->browser == WEUA_Emacs ? YES : NO;
701 return self->browser == WEUA_Wget ? YES : NO;
703 - (BOOL)isWebFolder {
704 return self->browser == WEUA_WebFolder ? YES : NO;
707 return self->browser == WEUA_Mozilla ? YES : NO;
710 return self->browser == WEUA_OmniWeb ? YES : NO;
713 return self->browser == WEUA_iCab ? YES : NO;
715 - (BOOL)isKonqueror {
716 return self->browser == WEUA_Konqueror ? YES : NO;
721 - (BOOL)isWindowsBrowser {
722 return self->os == WEOS_WINDOWS ? YES : NO;
724 - (BOOL)isLinuxBrowser {
725 return self->os == WEOS_LINUX ? YES : NO;
727 - (BOOL)isMacBrowser {
728 return self->os == WEOS_MACOS ? YES : NO;
730 - (BOOL)isSunOSBrowser {
731 return self->os == WEOS_SUNOS ? YES : NO;
733 - (BOOL)isUnixBrowser {
741 - (BOOL)isX11Browser {
742 if ([self isTextModeBrowser])
744 if (![self isUnixBrowser])
751 - (id)copyWithZone:(NSZone *)_zone {
752 return [self retain];
757 - (NSString *)description {
760 s = [NSMutableString stringWithFormat:@"<%@[0x%08X]:",
761 NSStringFromClass([self class]), self];
763 //[s appendFormat:@" ua='%@'", self->userAgent];
764 [s appendFormat:@" type=%@ v%i.%i>",
765 [self userAgentType],
766 self->browserMajorVersion, self->browserMinorVersion];
767 [s appendFormat:@" os=%@", [self os]];
768 [s appendFormat:@" cpu=%@", [self cpu]];
770 if ([self isFastTableBrowser]) [s appendString:@" fast-tbl"];
771 if ([self isCSS1Browser]) [s appendString:@" css1"];
772 if ([self isCSS2Browser]) [s appendString:@" css2"];
773 if ([self isXULBrowser]) [s appendString:@" xul"];
774 if ([self isTextModeBrowser]) [s appendString:@" text"];
775 if ([self isRobot]) [s appendString:@" robot"];
776 if ([self isJavaScriptBrowser]) [s appendString:@" js"];
777 if ([self isVBScriptBrowser]) [s appendString:@" vb"];
779 [s appendString:@">"];
783 @end /* WEClientCapabilities */
785 static NSString *ClientCapsCacheKey = @"WEClientCapabilities";
787 @implementation WORequest(ClientCapabilities)
789 - (WEClientCapabilities *)clientCapabilities {
791 WEClientCapabilities *ccaps;
792 NSMutableDictionary *md;
794 if ((ua = [self userInfo]) == nil) {
795 ccaps = [WEClientCapabilities alloc];
796 if ((ccaps = [ccaps initWithRequest:self]) == nil)
798 ccaps = [ccaps autorelease];
800 ua = [[NSDictionary alloc] initWithObjects:&ccaps
801 forKeys:&ClientCapsCacheKey
803 [self setUserInfo:ua];
808 if ((ccaps = [ua objectForKey:ClientCapsCacheKey]))
811 ccaps = [WEClientCapabilities alloc];
812 if ((ccaps = [ccaps initWithRequest:self]) == nil)
814 ccaps = [ccaps autorelease];
816 md = [ua mutableCopy];
817 [md setObject:ccaps forKey:ClientCapsCacheKey];
820 [self setUserInfo:ua];
825 @end /* WORequest(ClientCapabilities) */
827 static NSString *WEClientDetectorFormName = @"WEClientDetect";
829 @implementation JSClientCapabilityDetector
831 - (id)initWithName:(NSString *)_name
832 associations:(NSDictionary *)_config
833 template:(WOElement *)_c
835 if ((self = [super initWithName:_name associations:_config template:_c])) {
836 self->formName = OWGetProperty(_config, @"formName");
837 self->clientCaps = OWGetProperty(_config, @"clientCaps");
843 [self->formName release];
844 [self->clientCaps release];
848 - (NSString *)_formNameInContext:(WOContext *)_ctx {
850 return [self->formName stringValueInComponent:[_ctx component]];
854 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
855 if (![_ctx isInForm]) {
857 warnWithFormat:@"you must use %@ inside a form !",
858 NSStringFromClass([self class])];
862 if (![[[_ctx request] clientCapabilities] isJavaScriptBrowser])
863 /* only works on JavaScript browsers ... */
866 [_response appendContentString:@"<input type='hidden' name='"];
867 [_response appendContentString:WEClientDetectorFormName];
868 [_response appendContentString:@"' value='browserConfig' />"];
870 [_response appendContentString:@"<script language='JavaScript'>\n"];
871 [_response appendContentString:@"<!-- hide\n"];
873 [_response appendContentString:@"// -->\n"];
874 [_response appendContentString:@"</script>"];
877 @end /* JSClientCapabilityDetector */
880 Netscape 4.76, Windows NT 4
881 'Mozilla/4.76 [en] (WinNT; U)'
883 Netscape 6, Windows NT 4
884 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m18) Gecko/20001108 Netscape6/6.0'
886 Netscape Navigator 3.01[de], MacOS 8.1
887 'Mozilla/3.01 [de]-C-MACOS8 (Macintosh; I; PPC)'
889 Netscape Communicator 4.51, SuSE Linux 6.1
890 'Mozilla/4.51 [en] (X11; I; Linux 2.2.13 i686)'
892 Mozilla M17, Windows NT 4
893 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m17) Gecko/20000807'
895 Internet Explorer 5.5, Windows NT 4
896 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)'
898 Internet Explorer 3.0.1, MacOS 8.1
899 'Mozilla/3.0 (compatible; MSIE 3.0.1; Mac_PowerPC; Mac OS8)'
901 Internet Explorer 5.0, MacOS 8.1
902 'Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)'
904 Internet Explorer 5.0, SPARC Solaris 2.6 (trex)
905 'Mozilla/4.0 (compatible; MSIE 5.0; SunOS 5.6 sun4u; X11)'
907 Konqueror/2.0, SuSE Linux 7.0
908 'Mozilla/5.0 (compatible; Konqueror/2.0; X11); Supports MD5-Digest; Supports gzip encoding'
910 Lynx, SuSE Linux 6.1 (marvin)
911 'Lynx/2.8rel.2 libwww-FM/2.14'
913 Lynx, SPARC Solaris 2.6 (trex)
914 'Lynx/2.7 libwww-FM/2.14'
916 Opera 4.02, Windows NT 4
917 'Mozilla/4.73 (Windows NT 4.0; U) Opera 4.02 [en]'
919 Opera 5.0, Windows NT 4
920 'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 5.0 [en]'
922 Amaya 4.0, Windows NT 4
923 'amaya/V4.0 libwww/5.3.1'
925 XEmacs, SuSE Linux 6.1
926 'Emacs-W3/4.0pre.39 URL/p4.0pre.39 (i686-pc-linux; X11)'
928 XEmacs, SuSE Linux 7.2
929 'Emacs-W3/4.0pre.46 URL/p4.0pre.46 (i386-suse-linux; X11)'
934 Windows 'WebFolder' NT4
935 'Microsoft Data Access Internet Publishing Provider Cache Manager'
936 'Mozilla/2.0 (compatible; MS FrontPage 4.0)'
939 Windows 98 IE 5 WebFolders
940 'Microsoft Data Access Internet Publishing Provider DAV'
943 'OmniWeb/3.0.2 OWF/1999C'
945 Links, SuSE Linux 6.1 (marvin)
946 'Links (0.95; Linux 2.2.13 i686)'
952 fetch/1.0 Darwin/1.3.7 (Power Macintosh)
955 WebDAVFS/1.0 Darwin/5.1 (Power Macintosh)
958 WebDAVFS/1.2.1 (01218000) Darwin/6.1 (Power Macintosh)
961 'cadaver/0.17.0 neon/0.12.0-dev'
964 'GoLive/5. 0 [] (Windows 98; RATBERT)'
967 - (very) small X11 web browser
976 Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework
979 Outlook 2000 on W2K with M$ Web Publishing Assistent
980 'Microsoft HTTP Post (RFC1867)'
982 CURL program (libcurl)
983 'curl/7.9.8 (i686-suse-linux) libcurl 7.9.8 (OpenSSL 0.9.6g) (ipv6 enabled)'
985 Evolution 1.0.8 with Exchange Connector (WebDAV)
988 Outlook 2002 on W2K (HotMail HTTP access)
989 'Microsoft-Outlook/10.0 (TmstmpExt)'
991 Outlook Express 5.5 on W2K (HotMail HTTP access)
992 'Outlook-Express/5.5 (MSIE 5.5; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
994 Outlook Express 6.0 on W2K (HotMail HTTP access)
995 'Outlook-Express/6.0 (MSIE 6.0; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
997 Nautilus (GNOME Virtual Filesystem)
1000 Konqueror 3.0.3 (SuSE 8.1)
1001 - does not send a user-agent in webdav:// mode !
1004 'neon/0.23.5 NeonConnection 0.0'
1006 Safari v74 (MacOSX 10.2)
1007 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/74 (KHTML, like Gecko) Safari/74'
1008 - why does it say Mozilla/5.0 ??
1010 Evolution 1.4.0 with Exchange Connector 1.4.0 (SuSE 8.2)
1013 Mozilla Firebird 0.6 (MacOSX 10.2)
1014 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6'
1016 SOUP (Evo OGo Connector by Anders)
1019 Entourage/X (Entourage WebDAV 10.1.4, MacOSX)
1020 'Entourage/10.0 (Mac_PowerPC; DigExt; TmstmpExt)'
1022 Some unknown iCal.app
1025 NetNewsWire full version:
1026 'NetNewsWire/1.0.5 (Mac OS X; http://ranchero.com/netnewswire/)'
1028 NetNewsWire lite version:
1029 'NetNewsWire/1.0.3 (Mac OS X; Lite; http://ranchero.com/netnewswire/)'
1032 'xmlrpclib.py/1.0.0 (by www.pythonware.com)'
1034 Windows 2000 IE 6 WebFolders
1035 'Microsoft Data Access Internet Publishing Provider DAV 1.1'
1037 Morgul, Windows WebDAV client
1040 Apple iSync v122 / CoreFoundation Network
1043 Kung-Log (WebServicesCore)
1044 'Kung-Log/1.3 (Macintosh; U; PPC Mac OS X) WebServicesCore'
1046 Ecto (WebServicesCore)
1047 'ecto (Macintosh; U; PPC Mac OS X) WebServicesCore'
1053 'Goliath/1.0.1 (Macintosh-Carbon; PPC)'
1059 'Mediapartners-Google/2.1'