2 Copyright (C) 2000-2006 SKYRIX Software AG
3 Copyright (C) 2006 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
76 #define WEOS_UNKNOWN 0
77 #define WEOS_WINDOWS 1
82 #define WECPU_UNKNOWN 0
87 @interface WEClientCapabilities(Privates)
88 - (id)initWithRequest:(WORequest *)_request;
91 @implementation WEClientCapabilities
93 - (id)initWithRequest:(WORequest *)_request {
97 int defaultOS = WEOS_UNKNOWN;
98 int defaultCPU = WECPU_UNKNOWN;
102 if ((ac = [_request headerForKey:@"accept-charset"])) {
103 /* not really correct ..., eg could have quality "0" ! */
104 ac = [ac lowercaseString];
105 if ([ac rangeOfString:@"utf-8"].length > 0)
106 self->flags.acceptUTF8 = 1;
109 /* process user-agent */
111 self->userAgent = [[_request headerForKey:@"user-agent"] copy];
112 ua = [self->userAgent cString];
114 /* no user-agent, eg telnet */
120 if ((tmp = strstr(ua, "Opera"))) {
121 /* Opera (can fake to be MSIE or Netscape) */
122 self->browser = WEUA_Opera;
124 /* go to next space */
125 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
127 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
129 self->browserMajorVersion = atoi(tmp);
130 if ((tmp = index(tmp, '.'))) {
132 self->browserMinorVersion = atoi(tmp);
135 else if (strstr(ua, "NeonConnection") != NULL ||
136 strstr(ua, "ZIDEStore") != NULL ||
137 strstr(ua, "ZideLook-Codeon") != NULL) {
138 self->browser = WEUA_ZideLook;
139 self->browserMinorVersion = 0;
140 self->browserMajorVersion = 0;
142 else if ((tmp = strstr(ua, "Safari/"))) {
143 /* Hm, Safari says it is a Mozilla/5.0 ? */
145 self->browser = WEUA_Safari;
146 tmp += 7; /* skip "Safari/" */
147 combinedVersion = atoi(tmp);
148 /* well, don't know how this is supposed to work? 100=v1.1 */
149 if (combinedVersion == 100 /* 100 is v1.1 */) {
150 self->browserMajorVersion = 1;
151 self->browserMinorVersion = 1;
154 /* watch for upcoming versions ... */
155 self->browserMajorVersion = combinedVersion / 100;
158 else if (strstr(ua, "Outlook-Express/")) {
159 /* Outlook Express 5.5 mailbox access via http */
160 self->browser = WEUA_MSOutlookExpress;
162 else if (strstr(ua, "Outlook Express/")) {
163 /* Outlook Express 5.0 mailbox access via http */
164 self->browser = WEUA_MSOutlookExpress;
166 else if (strstr(ua, "Microsoft-Outlook/")) {
167 /* Outlook 2002 mailbox access via http */
168 self->browser = WEUA_MSOutlook;
170 else if (strstr(ua, "Microsoft HTTP Post")) {
171 /* Outlook 2000 with WebPublishing Assistent */
172 self->browser = WEUA_MSWebPublisher;
174 else if (strstr(ua, "Entourage/10")) {
175 /* Entourage MacOSX 10.1.4 */
176 self->browser = WEUA_Entourage;
178 else if (strstr(ua, "Microsoft-WebDAV-MiniRedir/5")) {
179 /* WebFolders Win XP SP 2 */
180 self->browser = WEUA_WebFolder;
182 else if ((tmp = strstr(ua, "MSIE"))) {
183 /* Internet Explorer */
184 self->browser = WEUA_IE;
186 /* go to next space */
187 while (!isspace(*tmp) && (*tmp != '\0')) tmp++;
189 while (isspace(*tmp) && (*tmp != '\0')) tmp++;
191 self->browserMajorVersion = atoi(tmp);
192 if ((tmp = index(tmp, '.'))) {
194 self->browserMinorVersion = atoi(tmp);
197 else if ((tmp = strstr(ua, "Konqueror"))) {
198 /* Konqueror (KDE2 FileManager) */
199 self->browser = WEUA_Konqueror;
201 if ((tmp = index(tmp, '/'))) {
203 self->browserMajorVersion = atoi(tmp);
204 if ((tmp = index(tmp, '.'))) {
206 self->browserMinorVersion = atoi(tmp);
210 else if ((tmp = strstr(ua, "Netscape6"))) {
212 self->browser = WEUA_Netscape;
214 if ((tmp = index(tmp, '/'))) {
216 self->browserMajorVersion = atoi(tmp);
217 if ((tmp = index(tmp, '.'))) {
219 self->browserMinorVersion = atoi(tmp);
223 else if (strstr(ua, "Lynx")) {
225 self->browser = WEUA_Lynx;
227 else if (strstr(ua, "Links")) {
229 self->browser = WEUA_Links;
231 else if (strstr(ua, "gnome-vfs")) {
233 self->browser = WEUA_GNOMEVFS;
235 else if (strstr(ua, "cadaver")) {
236 /* Cadaver DAV browser */
237 self->browser = WEUA_CADAVER;
239 else if (strstr(ua, "GoLive")) {
241 self->browser = WEUA_GOLIVE;
243 else if (strstr(ua, "DAV.pm")) {
245 self->browser = WEUA_PerlHTTPDAV;
247 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "fetch/") != NULL) {
248 /* MacOSX 10.0 DAV FileSystem */
249 self->browser = WEUA_MACOSX_DAVFS;
251 else if (strstr(ua, "Darwin") != NULL && strstr(ua, "WebDAVFS/") != NULL) {
252 /* MacOSX DAV FileSystem */
253 self->browser = WEUA_MACOSX_DAVFS;
255 else if (strstr(ua, "OmniWeb")) {
257 self->browser = WEUA_OmniWeb;
259 else if (strstr(ua, "Evolution")) {
261 self->browser = WEUA_Evolution;
263 else if (strstr(ua, "Soup/")) {
264 /* SOUP (GNOME WebDAV library) */
265 self->browser = WEUA_SOUP;
267 else if (strstr(ua, "amaya")) {
269 self->browser = WEUA_Amaya;
271 else if (strstr(ua, "NetNewsWire/")) {
273 self->browser = WEUA_NetNewsWire;
275 else if (strstr(ua, "Dillo")) {
277 self->browser = WEUA_Dillo;
279 else if (strstr(ua, "Java")) {
281 self->browser = WEUA_JavaSDK;
283 else if (strstr(ua, "Python-urllib")) {
284 /* Python URL module */
285 self->browser = WEUA_PythonURLLIB;
287 else if (strstr(ua, "xmlrpclib.py/")) {
288 /* Python XML-RPC module */
289 self->browser = WEUA_xmlrpclib_py;
291 else if (strstr(ua, "Emacs")) {
293 self->browser = WEUA_Emacs;
295 else if (strstr(ua, "iCab")) {
297 self->browser = WEUA_iCab;
299 else if (strstr(ua, "Wget")) {
301 self->browser = WEUA_Wget;
303 else if (strstr(ua, "DAVAccess")) {
304 /* Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework */
305 self->browser = WEUA_AppleDAVAccess;
307 else if (strstr(ua, "DAVKit/")) {
308 /* some iCal 1.x DAV Access Framework, report as Apple DAV access */
309 self->browser = WEUA_AppleDAVAccess;
311 else if (strstr(ua, "Microsoft Data Access Internet Publishing Provider")) {
313 self->browser = WEUA_WebFolder;
315 else if (strstr(ua, "Microsoft Office Protocol Discovery")) {
316 /* Word 2003, treat as WebFolder */
317 self->browser = WEUA_WebFolder;
319 else if (strstr(ua, "curl")) {
321 self->browser = WEUA_CURL;
323 else if (strstr(ua, "Mozilla")) {
324 /* other Netscape browser */
325 if (strstr(ua, "Mozilla/5")) {
326 self->browser = WEUA_Mozilla;
327 self->browserMajorVersion = 5;
329 else if (strstr(ua, "Mozilla/4")) {
330 self->browser = WEUA_Netscape;
331 self->browserMajorVersion = 4;
334 NSLog(@"%s: Unknown Mozilla Browser: user-agent='%@'",
335 __PRETTY_FUNCTION__, self->userAgent);
338 else if (strstr(ua, "Morgul")) {
339 self->browser = WEUA_Morgul;
341 else if (strstr(ua, "WebDrive")) {
342 self->browser = WEUA_WebDrive;
344 else if (strstr(ua, "CFNetwork/1.1")) {
345 self->browser = WEUA_CFNetwork;
347 else if (strstr(ua, "Kung-Log/")) {
348 self->browser = WEUA_KungLog;
350 else if (strstr(ua, "ecto")) {
351 self->browser = WEUA_Ecto;
353 else if (strstr(ua, "NewsFire")) {
354 self->browser = WEUA_NewsFire;
356 else if (strstr(ua, "Goliath")) {
357 self->browser = WEUA_Goliath;
359 else if (strstr(ua, "SOPE/")) {
360 self->browser = WEUA_SOPE;
362 else if (strstr(ua, "Mediapartners-Google/")) {
363 self->browser = WEUA_Google;
366 /* unknown browser */
367 self->browser = WEUA_UNKNOWN;
369 if (self->userAgent) {
370 NSLog(@"%s: Unknown WebClient: user-agent='%@'",
371 __PRETTY_FUNCTION__, self->userAgent);
377 if (strstr(ua, "Windows") != NULL || strstr(ua, "WinNT") != NULL)
378 self->os = WEOS_WINDOWS;
379 else if (strstr(ua, "Linux"))
380 self->os = WEOS_LINUX;
381 else if (strstr(ua, "Mac"))
382 self->os = WEOS_MACOS;
383 else if (strstr(ua, "SunOS"))
384 self->os = WEOS_SUNOS;
386 self->os = defaultOS;
390 if (strstr(ua, "sun4u"))
391 self->cpu = WECPU_SPARC;
392 else if (strstr(ua, "i686") || strstr(ua, "i586"))
393 self->cpu = WECPU_IX86;
394 else if (strstr(ua, "PowerPC") || strstr(ua, "ppc") || strstr(ua, "PPC"))
395 self->cpu = WECPU_PPC;
396 else if (self->os == WEOS_WINDOWS)
397 /* assume ix86 if OS is Windows .. */
398 self->cpu = WECPU_IX86;
400 self->cpu = defaultCPU;
406 [self->userAgent release];
412 - (NSString *)userAgent {
413 return self->userAgent;
416 - (NSString *)userAgentType {
417 switch (self->browser) {
418 case WEUA_IE: return @"IE";
419 case WEUA_Netscape: return @"Netscape";
420 case WEUA_Lynx: return @"Lynx";
421 case WEUA_Links: return @"Links";
422 case WEUA_Opera: return @"Opera";
423 case WEUA_Amaya: return @"Amaya";
424 case WEUA_Emacs: return @"Emacs";
425 case WEUA_Wget: return @"Wget";
426 case WEUA_WebFolder: return @"WebFolder";
427 case WEUA_DAVFS: return @"DAVFS";
428 case WEUA_MACOSX_DAVFS: return @"MacOSXDAVFS";
429 case WEUA_CADAVER: return @"Cadaver";
430 case WEUA_GOLIVE: return @"GoLive";
431 case WEUA_Mozilla: return @"Mozilla";
432 case WEUA_OmniWeb: return @"OmniWeb";
433 case WEUA_iCab: return @"iCab";
434 case WEUA_Konqueror: return @"Konqueror";
435 case WEUA_Dillo: return @"Dillo";
436 case WEUA_JavaSDK: return @"Java";
437 case WEUA_PythonURLLIB: return @"Python-urllib";
438 case WEUA_AppleDAVAccess: return @"AppleDAVAccess";
439 case WEUA_MSWebPublisher: return @"MSWebPublisher";
440 case WEUA_CURL: return @"CURL";
441 case WEUA_Evolution: return @"Evolution";
442 case WEUA_SOUP: return @"SOUP";
443 case WEUA_MSOutlook: return @"MSOutlook";
444 case WEUA_MSOutlookExpress: return @"MSOutlookExpress";
445 case WEUA_GNOMEVFS: return @"GNOME-VFS";
446 case WEUA_ZideLook: return @"ZideLook";
447 case WEUA_Safari: return @"Safari";
448 case WEUA_Entourage: return @"Entourage";
449 case WEUA_NetNewsWire: return @"NetNewsWire";
450 case WEUA_xmlrpclib_py: return @"xmlrpclib.py";
451 case WEUA_Morgul: return @"Morgul";
452 case WEUA_KungLog: return @"KungLog";
453 case WEUA_Ecto: return @"Ecto";
454 case WEUA_NewsFire: return @"NewsFire";
455 case WEUA_Goliath: return @"Goliath";
456 case WEUA_PerlHTTPDAV: return @"PerlHTTPDAV";
457 case WEUA_Google: return @"Google";
458 case WEUA_WebDrive: return @"WebDrive";
459 default: return @"unknown";
464 case WEOS_WINDOWS: return @"Windows";
465 case WEOS_LINUX: return @"Linux";
466 case WEOS_MACOS: return @"MacOS";
467 case WEOS_SUNOS: return @"SunOS";
468 default: return @"unknown";
473 case WECPU_IX86: return @"ix86";
474 case WECPU_SPARC: return @"sparc";
475 case WECPU_PPC: return @"ppc";
476 default: return @"unknown";
480 - (unsigned char)majorVersion {
481 return self->browserMajorVersion;
483 - (unsigned char)minorVersion {
484 return self->browserMinorVersion;
487 /* browser capabilities */
489 - (BOOL)isJavaScriptBrowser {
490 switch (self->browser) {
503 - (BOOL)isVBScriptBrowser {
504 switch (self->browser) {
513 - (BOOL)isFastTableBrowser {
514 switch (self->browser) {
526 return (self->browserMajorVersion >= 6)
534 - (BOOL)isCSS2Browser {
535 switch (self->browser) {
536 case WEUA_IE: return (self->browserMajorVersion >= 5) ? YES : NO;
537 case WEUA_Netscape: return (self->browserMajorVersion >= 6) ? YES : NO;
538 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
539 case WEUA_Mozilla: return YES;
540 case WEUA_Safari: return YES;
541 case WEUA_Konqueror: return NO;
546 - (BOOL)isCSS1Browser {
547 switch (self->browser) {
548 case WEUA_IE: return (self->browserMajorVersion >= 4) ? YES : NO;
549 case WEUA_Netscape: return (self->browserMajorVersion >= 4) ? YES : NO;
550 case WEUA_Opera: return (self->browserMajorVersion >= 4) ? YES : NO;
551 case WEUA_Safari: return YES;
552 case WEUA_Konqueror: return NO;
557 - (BOOL)ignoresCSSOnFormElements {
558 if (self->browser == WEUA_Safari) /* Safari always displays Aqua buttons */
561 return [self isCSS1Browser] ? NO : YES;
564 - (BOOL)isXULBrowser {
565 if (self->browser == WEUA_Safari) // TODO: Safari supports some XUL stuff
567 if ((self->browser == WEUA_Netscape) && (self->browserMajorVersion >= 6))
569 if (self->browser == WEUA_Mozilla)
574 - (BOOL)isTextModeBrowser {
575 if (self->browser == WEUA_Lynx) return YES;
576 if (self->browser == WEUA_Links) return YES;
577 if (self->browser == WEUA_Emacs) return YES;
581 - (BOOL)isIFrameBrowser {
582 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
585 /* as suggested in OGo bug #634 */
586 if ((self->browser == WEUA_Mozilla) && (self->browserMajorVersion >= 5))
593 if (self->browser == WEUA_Wget) return YES;
594 if (self->browser == WEUA_JavaSDK) return YES;
595 if (self->browser == WEUA_PythonURLLIB) return YES;
596 if (self->browser == WEUA_Google) return YES;
599 - (BOOL)isDAVClient {
600 if (self->browser == WEUA_WebFolder) return YES;
601 if (self->browser == WEUA_DAVFS) return YES;
602 if (self->browser == WEUA_MACOSX_DAVFS) return YES;
603 if (self->browser == WEUA_CADAVER) return YES;
604 if (self->browser == WEUA_GOLIVE) return YES;
605 if (self->browser == WEUA_AppleDAVAccess) return YES;
606 if (self->browser == WEUA_Evolution) return YES;
607 if (self->browser == WEUA_SOUP) return YES;
608 if (self->browser == WEUA_MSOutlook) return YES;
609 if (self->browser == WEUA_MSOutlookExpress) return YES;
610 if (self->browser == WEUA_GNOMEVFS) return YES;
611 if (self->browser == WEUA_ZideLook) return YES;
612 if (self->browser == WEUA_Entourage) return YES;
613 if (self->browser == WEUA_Morgul) return YES;
614 if (self->browser == WEUA_Goliath) return YES;
615 if (self->browser == WEUA_PerlHTTPDAV) return YES;
616 if (self->browser == WEUA_WebDrive) return YES;
620 - (BOOL)isXmlRpcClient {
621 if (self->browser == WEUA_xmlrpclib_py) return YES;
622 if (self->browser == WEUA_KungLog) return YES;
623 if (self->browser == WEUA_Ecto) return YES;
626 - (BOOL)isBLogClient {
627 if (self->browser == WEUA_KungLog) return YES;
628 if (self->browser == WEUA_Ecto) return YES;
631 - (BOOL)isRSSClient {
632 if (self->browser == WEUA_NetNewsWire) return YES;
633 if (self->browser == WEUA_NewsFire) return YES;
637 - (BOOL)doesSupportCSSOverflow {
638 if (![self isCSS1Browser])
640 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
646 - (BOOL)doesSupportDHTMLDragAndDrop {
647 if (![self isJavaScriptBrowser])
649 if (self->os != WEOS_WINDOWS)
651 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
656 - (BOOL)doesSupportXMLDataIslands {
657 if ((self->browser == WEUA_IE) && (self->browserMajorVersion >= 5))
662 - (BOOL)doesSupportUTF8Encoding {
663 if (self->flags.acceptUTF8)
664 /* explicit UTF-8 support signaled in HTTP header */
667 switch (self->browser) {
674 /* browser so new, that they always supported UTF-8 ... */
677 if (self->browserMajorVersion >= 5)
679 return NO; // TODO: find out, whether IE 4 gurantees UTF-8 support
687 - (BOOL)isInternetExplorer {
688 return self->browser == WEUA_IE ? YES : NO;
690 - (BOOL)isInternetExplorer5 {
691 return (self->browser == WEUA_IE) && (self->browserMajorVersion == 5)
696 return self->browser == WEUA_Netscape ? YES : NO;
698 - (BOOL)isNetscape6 {
699 return (self->browser == WEUA_Netscape) && (self->browserMajorVersion == 6)
704 return self->browser == WEUA_Lynx ? YES : NO;
707 return self->browser == WEUA_Opera ? YES : NO;
710 return self->browser == WEUA_Amaya ? YES : NO;
713 return self->browser == WEUA_Emacs ? YES : NO;
716 return self->browser == WEUA_Wget ? YES : NO;
718 - (BOOL)isWebFolder {
719 return self->browser == WEUA_WebFolder ? YES : NO;
722 return self->browser == WEUA_Mozilla ? YES : NO;
725 return self->browser == WEUA_OmniWeb ? YES : NO;
728 return self->browser == WEUA_iCab ? YES : NO;
730 - (BOOL)isKonqueror {
731 return self->browser == WEUA_Konqueror ? YES : NO;
736 - (BOOL)isWindowsBrowser {
737 return self->os == WEOS_WINDOWS ? YES : NO;
739 - (BOOL)isLinuxBrowser {
740 return self->os == WEOS_LINUX ? YES : NO;
742 - (BOOL)isMacBrowser {
743 return self->os == WEOS_MACOS ? YES : NO;
745 - (BOOL)isSunOSBrowser {
746 return self->os == WEOS_SUNOS ? YES : NO;
748 - (BOOL)isUnixBrowser {
756 - (BOOL)isX11Browser {
757 if ([self isTextModeBrowser])
759 if (![self isUnixBrowser])
766 - (id)copyWithZone:(NSZone *)_zone {
767 return [self retain];
772 - (NSString *)description {
775 s = [NSMutableString stringWithFormat:@"<%@[0x%08X]:",
776 NSStringFromClass([self class]), self];
778 //[s appendFormat:@" ua='%@'", self->userAgent];
779 [s appendFormat:@" type=%@ v%i.%i>",
780 [self userAgentType],
781 self->browserMajorVersion, self->browserMinorVersion];
782 [s appendFormat:@" os=%@", [self os]];
783 [s appendFormat:@" cpu=%@", [self cpu]];
785 if ([self isFastTableBrowser]) [s appendString:@" fast-tbl"];
786 if ([self isCSS1Browser]) [s appendString:@" css1"];
787 if ([self isCSS2Browser]) [s appendString:@" css2"];
788 if ([self isXULBrowser]) [s appendString:@" xul"];
789 if ([self isTextModeBrowser]) [s appendString:@" text"];
790 if ([self isRobot]) [s appendString:@" robot"];
791 if ([self isJavaScriptBrowser]) [s appendString:@" js"];
792 if ([self isVBScriptBrowser]) [s appendString:@" vb"];
794 [s appendString:@">"];
798 @end /* WEClientCapabilities */
800 static NSString *ClientCapsCacheKey = @"WEClientCapabilities";
802 @implementation WORequest(ClientCapabilities)
804 - (WEClientCapabilities *)clientCapabilities {
806 WEClientCapabilities *ccaps;
807 NSMutableDictionary *md;
809 if ((ua = [self userInfo]) == nil) {
810 ccaps = [WEClientCapabilities alloc];
811 if ((ccaps = [ccaps initWithRequest:self]) == nil)
813 ccaps = [ccaps autorelease];
815 ua = [[NSDictionary alloc] initWithObjects:&ccaps
816 forKeys:&ClientCapsCacheKey
818 [self setUserInfo:ua];
823 if ((ccaps = [ua objectForKey:ClientCapsCacheKey]))
826 ccaps = [WEClientCapabilities alloc];
827 if ((ccaps = [ccaps initWithRequest:self]) == nil)
829 ccaps = [ccaps autorelease];
831 md = [ua mutableCopy];
832 [md setObject:ccaps forKey:ClientCapsCacheKey];
835 [self setUserInfo:ua];
840 @end /* WORequest(ClientCapabilities) */
842 static NSString *WEClientDetectorFormName = @"WEClientDetect";
844 @implementation JSClientCapabilityDetector
846 - (id)initWithName:(NSString *)_name
847 associations:(NSDictionary *)_config
848 template:(WOElement *)_c
850 if ((self = [super initWithName:_name associations:_config template:_c])) {
851 self->formName = OWGetProperty(_config, @"formName");
852 self->clientCaps = OWGetProperty(_config, @"clientCaps");
858 [self->formName release];
859 [self->clientCaps release];
863 - (NSString *)_formNameInContext:(WOContext *)_ctx {
865 return [self->formName stringValueInComponent:[_ctx component]];
869 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
870 if (![_ctx isInForm]) {
872 warnWithFormat:@"you must use %@ inside a form !",
873 NSStringFromClass([self class])];
877 if (![[[_ctx request] clientCapabilities] isJavaScriptBrowser])
878 /* only works on JavaScript browsers ... */
881 [_response appendContentString:@"<input type='hidden' name='"];
882 [_response appendContentString:WEClientDetectorFormName];
883 [_response appendContentString:@"' value='browserConfig' />"];
885 [_response appendContentString:@"<script language='JavaScript'>\n"];
886 [_response appendContentString:@"<!-- hide\n"];
888 [_response appendContentString:@"// -->\n"];
889 [_response appendContentString:@"</script>"];
892 @end /* JSClientCapabilityDetector */
895 Netscape 4.76, Windows NT 4
896 'Mozilla/4.76 [en] (WinNT; U)'
898 Netscape 6, Windows NT 4
899 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m18) Gecko/20001108 Netscape6/6.0'
901 Netscape Navigator 3.01[de], MacOS 8.1
902 'Mozilla/3.01 [de]-C-MACOS8 (Macintosh; I; PPC)'
904 Netscape Communicator 4.51, SuSE Linux 6.1
905 'Mozilla/4.51 [en] (X11; I; Linux 2.2.13 i686)'
907 Mozilla M17, Windows NT 4
908 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; m17) Gecko/20000807'
910 Internet Explorer 5.5, Windows NT 4
911 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)'
913 Internet Explorer 3.0.1, MacOS 8.1
914 'Mozilla/3.0 (compatible; MSIE 3.0.1; Mac_PowerPC; Mac OS8)'
916 Internet Explorer 5.0, MacOS 8.1
917 'Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)'
919 Internet Explorer 5.0, SPARC Solaris 2.6 (trex)
920 'Mozilla/4.0 (compatible; MSIE 5.0; SunOS 5.6 sun4u; X11)'
922 Konqueror/2.0, SuSE Linux 7.0
923 'Mozilla/5.0 (compatible; Konqueror/2.0; X11); Supports MD5-Digest; Supports gzip encoding'
925 Lynx, SuSE Linux 6.1 (marvin)
926 'Lynx/2.8rel.2 libwww-FM/2.14'
928 Lynx, SPARC Solaris 2.6 (trex)
929 'Lynx/2.7 libwww-FM/2.14'
931 Opera 4.02, Windows NT 4
932 'Mozilla/4.73 (Windows NT 4.0; U) Opera 4.02 [en]'
934 Opera 5.0, Windows NT 4
935 'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 4.0) Opera 5.0 [en]'
937 Amaya 4.0, Windows NT 4
938 'amaya/V4.0 libwww/5.3.1'
940 XEmacs, SuSE Linux 6.1
941 'Emacs-W3/4.0pre.39 URL/p4.0pre.39 (i686-pc-linux; X11)'
943 XEmacs, SuSE Linux 7.2
944 'Emacs-W3/4.0pre.46 URL/p4.0pre.46 (i386-suse-linux; X11)'
949 Windows 'WebFolder' NT4
950 'Microsoft Data Access Internet Publishing Provider Cache Manager'
951 'Mozilla/2.0 (compatible; MS FrontPage 4.0)'
954 Windows 98 IE 5 WebFolders
955 'Microsoft Data Access Internet Publishing Provider DAV'
958 'OmniWeb/3.0.2 OWF/1999C'
960 Links, SuSE Linux 6.1 (marvin)
961 'Links (0.95; Linux 2.2.13 i686)'
967 fetch/1.0 Darwin/1.3.7 (Power Macintosh)
970 WebDAVFS/1.0 Darwin/5.1 (Power Macintosh)
973 WebDAVFS/1.2.1 (01218000) Darwin/6.1 (Power Macintosh)
976 WebDAVFS/1.4.1 (01418000) Darwin/8.6.0 (Power Macintosh)
979 'cadaver/0.17.0 neon/0.12.0-dev'
982 'GoLive/5. 0 [] (Windows 98; RATBERT)'
985 - (very) small X11 web browser
994 Apple MacOSX 10.2.1 / iCal 1.0 DAV Access Framework
997 Outlook 2000 on W2K with M$ Web Publishing Assistent
998 'Microsoft HTTP Post (RFC1867)'
1000 CURL program (libcurl)
1001 'curl/7.9.8 (i686-suse-linux) libcurl 7.9.8 (OpenSSL 0.9.6g) (ipv6 enabled)'
1003 Evolution 1.0.8 with Exchange Connector (WebDAV)
1006 Outlook 2002 on W2K (HotMail HTTP access)
1007 'Microsoft-Outlook/10.0 (TmstmpExt)'
1009 Outlook Express 5.5 on W2K (HotMail HTTP access)
1010 'Outlook-Express/5.5 (MSIE 5.5; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
1012 Outlook Express 6.0 on W2K (HotMail HTTP access)
1013 'Outlook-Express/6.0 (MSIE 6.0; Windows NT 5.0; Q312461; T312461; TmstmpExt)'
1015 Nautilus (GNOME Virtual Filesystem)
1018 Konqueror 3.0.3 (SuSE 8.1)
1019 - does not send a user-agent in webdav:// mode !
1022 'neon/0.23.5 NeonConnection 0.0'
1024 Safari v74 (MacOSX 10.2)
1025 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/74 (KHTML, like Gecko) Safari/74'
1026 - why does it say Mozilla/5.0 ??
1028 Evolution 1.4.0 with Exchange Connector 1.4.0 (SuSE 8.2)
1031 Mozilla Firebird 0.6 (MacOSX 10.2)
1032 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6'
1034 SOUP (Evo OGo Connector by Anders)
1037 Entourage/X (Entourage WebDAV 10.1.4, MacOSX)
1038 'Entourage/10.0 (Mac_PowerPC; DigExt; TmstmpExt)'
1040 Some unknown iCal.app
1043 NetNewsWire full version:
1044 'NetNewsWire/1.0.5 (Mac OS X; http://ranchero.com/netnewswire/)'
1046 NetNewsWire lite version:
1047 'NetNewsWire/1.0.3 (Mac OS X; Lite; http://ranchero.com/netnewswire/)'
1050 'xmlrpclib.py/1.0.0 (by www.pythonware.com)'
1052 Windows 2000 IE 6 WebFolders
1053 'Microsoft Data Access Internet Publishing Provider DAV 1.1'
1055 Morgul, Windows WebDAV client
1058 Apple iSync v122 / CoreFoundation Network
1061 Kung-Log (WebServicesCore)
1062 'Kung-Log/1.3 (Macintosh; U; PPC Mac OS X) WebServicesCore'
1064 Ecto (WebServicesCore)
1065 'ecto (Macintosh; U; PPC Mac OS X) WebServicesCore'
1071 'Goliath/1.0.1 (Macintosh-Carbon; PPC)'
1077 'Mediapartners-Google/2.1'
1079 WebFolders Win XP SP2
1080 'Microsoft-WebDAV-MiniRedir/5.1.2600'
1083 'Microsoft Office Protocol Discovery'
1086 'WebDrive 7.10.1475 DAV'