Commit cda39631 authored by darin's avatar darin
Browse files

Reviewed by Dave.

	- implemented user-agent spoofing as described in bug 3044569

        * WebView.subproj/WebController.m: (-[WebController userAgentForURL:]):
	Find the suffix of the host name that contains exactly one dot, lower-case it,
	and look it up in the user-agent spoof table. For now, anything in the table
	pretends to be MacIE. Don't fret that this table is simple. We will complicate it
	as needed. The technique is flexible, even though it may not look it now.

        * WebView.subproj/WebControllerPrivate.h: Add userAgentWhenPretendingToBeMacIE field.
        * WebView.subproj/WebControllerPrivate.m:
        (-[WebControllerPrivate dealloc]): Release userAgentWhenPretendingToBeMacIE.
        (-[WebController _defaultsDidChange]): Release and nil userAgentWhenPretendingToBeMacIE.

        * Makefile.am: Added rules to build WebUserAgentSpoofTable.c using gperf.
        * WebView.subproj/WebUserAgentSpoofTable.c: Added. Generated file.
        * WebView.subproj/WebUserAgentSpoofTable.gperf: Added. Table

        * English.lproj/StringsNotToBeLocalized.txt: Update for above changes.

	- fixed a crash I saw in a simplistic way

        * WebView.subproj/WebHTMLViewPrivate.m: (-[WebHTMLView _elementAtPoint:]):
	Don't assert if the webFrame is nil, just return a partial dictionary.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@3073 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent fcbad401
2002-12-15 Darin Adler <darin@apple.com>
Reviewed by Dave.
- implemented user-agent spoofing as described in bug 3044569
* WebView.subproj/WebController.m: (-[WebController userAgentForURL:]):
Find the suffix of the host name that contains exactly one dot, lower-case it,
and look it up in the user-agent spoof table. For now, anything in the table
pretends to be MacIE. Don't fret that this table is simple. We will complicate it
as needed. The technique is flexible, even though it may not look it now.
* WebView.subproj/WebControllerPrivate.h: Add userAgentWhenPretendingToBeMacIE field.
* WebView.subproj/WebControllerPrivate.m:
(-[WebControllerPrivate dealloc]): Release userAgentWhenPretendingToBeMacIE.
(-[WebController _defaultsDidChange]): Release and nil userAgentWhenPretendingToBeMacIE.
* Makefile.am: Added rules to build WebUserAgentSpoofTable.c using gperf.
* WebView.subproj/WebUserAgentSpoofTable.c: Added. Generated file.
* WebView.subproj/WebUserAgentSpoofTable.gperf: Added. Table
* English.lproj/StringsNotToBeLocalized.txt: Update for above changes.
- fixed a crash I saw in a simplistic way
* WebView.subproj/WebHTMLViewPrivate.m: (-[WebHTMLView _elementAtPoint:]):
Don't assert if the webFrame is nil, just return a partial dictionary.
2002-12-15 Darin Adler <darin@apple.com>
Reviewed by Trey.
......
......@@ -70,6 +70,8 @@
"Library/Internet Plug-Ins"
"Library/Preferences/Explorer/Favorites.html"
"Lucida Grande"
"Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) AppleWebKit/%@ %@"
"Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) AppleWebKit/%@"
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko) %@"
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko)"
"NETSCAPE2"
......
......@@ -6,6 +6,12 @@ clean-am:
rm -rf $(SYMROOTS)/WebKit.framework
rm -rf $(SYMROOTS)/Safari.app/Frameworks/WebKit.framework
WebView.subproj/WebUserAgentSpoofTable.c: WebView.subproj/WebUserAgentSpoofTable.gperf Makefile.am previous-clean-timestamp
gperf -CEot -L 'ANSI-C' -k '*' -N _web_findSpoofTableEntry $< > $@
BUILT_SOURCES = WebView.subproj/WebUserAgentSpoofTable.c
CLEANFILES = $(BUILT_SOURCES)
previous-clean-timestamp: force-clean-timestamp
make clean && touch $@
......
......@@ -30,6 +30,10 @@
#import <WebFoundation/WebNSUserDefaultsExtras.h>
#import <WebFoundation/WebResourceHandle.h>
const struct UserAgentSpoofTableEntry *_web_findSpoofTableEntry(const char *, unsigned);
#include "WebUserAgentSpoofTable.c"
NSString *WebElementFrameKey = @"WebElementFrame";
NSString *WebElementImageKey = @"WebElementImage";
NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
......@@ -41,7 +45,6 @@
NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
NSString *WebElementStringKey = @"WebElementString";
@implementation WebController
- init
......@@ -358,13 +361,41 @@ - (NSString *)userAgentForURL:(NSURL *)URL
if (_private->userAgentOverride) {
return [[_private->userAgentOverride retain] autorelease];
}
if (_private->userAgent) {
return [[_private->userAgent retain] autorelease];
// Look to see if we need to spoof.
// First step is to get the host as a C-format string.
BOOL pretendToBeMacIE = NO;
NSString *host = [URL host];
char hostBuffer[256];
if (host && CFStringGetCString((CFStringRef)host, hostBuffer, sizeof(hostBuffer), kCFStringEncodingASCII)) {
// Next step is to find the last part of the name. The part with only one dot.
const char *nextToLastPeriod = NULL;
const char *lastPeriod = NULL;
char c;
char *p = hostBuffer;
while ((c = *p)) {
if (c == '.') {
nextToLastPeriod = lastPeriod;
lastPeriod = p;
} else {
*p = tolower(c);
}
++p;
}
// Now look up that last part in the gperf spoof table.
if (lastPeriod) {
const char *domain = nextToLastPeriod ? nextToLastPeriod + 1 : hostBuffer;
pretendToBeMacIE = _web_findSpoofTableEntry(domain, p - domain) != NULL;
}
}
NSString **userAgentStorage = pretendToBeMacIE
? &_private->userAgentWhenPretendingToBeMacIE : &_private->userAgent;
// Note that we currently don't look at the URL.
// Soon we will spoof different user agent strings for different web pages
// for best results, and that logic will go here.
NSString *userAgent = *userAgentStorage;
if (userAgent) {
return [[userAgent retain] autorelease];
}
// FIXME: Some day we will start reporting the actual CPU here instead of hardcoding PPC.
......@@ -373,16 +404,25 @@ - (NSString *)userAgentForURL:(NSURL *)URL
objectForInfoDictionaryKey:(id)kCFBundleVersionKey];
NSString *applicationName = _private->applicationNameForUserAgent;
NSString *userAgent;
if ([applicationName length]) {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko) %@",
language, sourceVersion, applicationName];
if (pretendToBeMacIE) {
if ([applicationName length]) {
userAgent = [NSString stringWithFormat:@"Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) AppleWebKit/%@ %@",
language, sourceVersion, applicationName];
} else {
userAgent = [NSString stringWithFormat:@"Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) AppleWebKit/%@",
language, sourceVersion];
}
} else {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko)",
language, sourceVersion];
if ([applicationName length]) {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko) %@",
language, sourceVersion, applicationName];
} else {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko)",
language, sourceVersion];
}
}
_private->userAgent = [userAgent retain];
*userAgentStorage = [userAgent retain];
return userAgent;
}
......
......@@ -31,6 +31,7 @@
NSString *applicationNameForUserAgent;
NSString *userAgentOverride;
NSString *userAgent;
NSString *userAgentWhenPretendingToBeMacIE;
BOOL defersCallbacks;
......
......@@ -65,6 +65,7 @@ - (void)dealloc
[applicationNameForUserAgent release];
[userAgentOverride release];
[userAgent release];
[userAgentWhenPretendingToBeMacIE release];
[controllerSetName release];
[topLevelFrameName release];
......@@ -335,6 +336,8 @@ - (void)_defaultsDidChange
{
[_private->userAgent release];
_private->userAgent = nil;
[_private->userAgentWhenPretendingToBeMacIE release];
_private->userAgentWhenPretendingToBeMacIE = nil;
}
@end
......@@ -172,20 +172,21 @@ - (NSDictionary *)_elementAtPoint:(NSPoint)point
WebView *webView = [self _web_parentWebView];
ASSERT(webView);
WebFrame *webFrame = [[webView controller] frameForView:webView];
ASSERT(webFrame);
NSString *frameName = [elementInfoWC objectForKey:WebElementLinkTargetFrameKey];
if ([frameName length] == 0) {
[elementInfo setObject:webFrame forKey:WebElementLinkTargetFrameKey];
} else {
WebFrame *wf = [webFrame findFrameNamed:frameName];
if (wf != nil)
[elementInfo setObject:wf forKey:WebElementLinkTargetFrameKey];
else
[elementInfo removeObjectForKey:WebElementLinkTargetFrameKey];
if (webFrame) {
NSString *frameName = [elementInfoWC objectForKey:WebElementLinkTargetFrameKey];
if ([frameName length] == 0) {
[elementInfo setObject:webFrame forKey:WebElementLinkTargetFrameKey];
} else {
WebFrame *wf = [webFrame findFrameNamed:frameName];
if (wf != nil)
[elementInfo setObject:wf forKey:WebElementLinkTargetFrameKey];
else
[elementInfo removeObjectForKey:WebElementLinkTargetFrameKey];
}
[elementInfo setObject:webFrame forKey:WebElementFrameKey];
}
[elementInfo setObject:webFrame forKey:WebElementFrameKey];
return [elementInfo autorelease];
}
......
/* ANSI-C code produced by gperf version 2.7.2 */
/* Command-line: gperf -CEot -L ANSI-C -k '*' -N _web_findSpoofTableEntry WebView.subproj/WebUserAgentSpoofTable.gperf */
struct UserAgentSpoofTableEntry { const char *name; };
/* maximum key range = 12, duplicates = 0 */
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static unsigned int
hash (register const char *str, register unsigned int len)
{
static const unsigned char asso_values[] =
{
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 0, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 0, 7, 0,
0, 0, 2, 0, 0, 0, 0, 21, 0, 0,
0, 0, 21, 21, 0, 0, 0, 0, 21, 0,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21
};
register int hval = len;
switch (hval)
{
default:
case 18:
hval += asso_values[(unsigned char)str[17]];
case 17:
hval += asso_values[(unsigned char)str[16]];
case 16:
hval += asso_values[(unsigned char)str[15]];
case 15:
hval += asso_values[(unsigned char)str[14]];
case 14:
hval += asso_values[(unsigned char)str[13]];
case 13:
hval += asso_values[(unsigned char)str[12]];
case 12:
hval += asso_values[(unsigned char)str[11]];
case 11:
hval += asso_values[(unsigned char)str[10]];
case 10:
hval += asso_values[(unsigned char)str[9]];
case 9:
hval += asso_values[(unsigned char)str[8]];
case 8:
hval += asso_values[(unsigned char)str[7]];
case 7:
hval += asso_values[(unsigned char)str[6]];
case 6:
hval += asso_values[(unsigned char)str[5]];
case 5:
hval += asso_values[(unsigned char)str[4]];
case 4:
hval += asso_values[(unsigned char)str[3]];
case 3:
hval += asso_values[(unsigned char)str[2]];
case 2:
hval += asso_values[(unsigned char)str[1]];
case 1:
hval += asso_values[(unsigned char)str[0]];
break;
}
return hval;
}
#ifdef __GNUC__
__inline
#endif
const struct UserAgentSpoofTableEntry *
_web_findSpoofTableEntry (register const char *str, register unsigned int len)
{
enum
{
TOTAL_KEYWORDS = 8,
MIN_WORD_LENGTH = 9,
MAX_WORD_LENGTH = 18,
MIN_HASH_VALUE = 9,
MAX_HASH_VALUE = 20
};
static const struct UserAgentSpoofTableEntry wordlist[] =
{
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{"watch.com"},
{"jaguar.com"},
{""}, {""},
{"hondacars.com"},
{"firstusa.com"},
{"microsoft.com"},
{""},
{"battle.net"},
{"hondaredriders.com"},
{""},
{"freebsd.org"}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register const char *s = wordlist[key].name;
if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key];
}
}
return 0;
}
struct UserAgentSpoofTableEntry { const char *name; };
%%
firstusa.com
jaguar.com
watch.com
hondaredriders.com
hondacars.com
microsoft.com
battle.net
freebsd.org
......@@ -30,6 +30,10 @@
#import <WebFoundation/WebNSUserDefaultsExtras.h>
#import <WebFoundation/WebResourceHandle.h>
const struct UserAgentSpoofTableEntry *_web_findSpoofTableEntry(const char *, unsigned);
#include "WebUserAgentSpoofTable.c"
NSString *WebElementFrameKey = @"WebElementFrame";
NSString *WebElementImageKey = @"WebElementImage";
NSString *WebElementImageAltStringKey = @"WebElementImageAltString";
......@@ -41,7 +45,6 @@
NSString *WebElementLinkTitleKey = @"WebElementLinkTitle";
NSString *WebElementStringKey = @"WebElementString";
@implementation WebController
- init
......@@ -358,13 +361,41 @@ - (NSString *)userAgentForURL:(NSURL *)URL
if (_private->userAgentOverride) {
return [[_private->userAgentOverride retain] autorelease];
}
if (_private->userAgent) {
return [[_private->userAgent retain] autorelease];
// Look to see if we need to spoof.
// First step is to get the host as a C-format string.
BOOL pretendToBeMacIE = NO;
NSString *host = [URL host];
char hostBuffer[256];
if (host && CFStringGetCString((CFStringRef)host, hostBuffer, sizeof(hostBuffer), kCFStringEncodingASCII)) {
// Next step is to find the last part of the name. The part with only one dot.
const char *nextToLastPeriod = NULL;
const char *lastPeriod = NULL;
char c;
char *p = hostBuffer;
while ((c = *p)) {
if (c == '.') {
nextToLastPeriod = lastPeriod;
lastPeriod = p;
} else {
*p = tolower(c);
}
++p;
}
// Now look up that last part in the gperf spoof table.
if (lastPeriod) {
const char *domain = nextToLastPeriod ? nextToLastPeriod + 1 : hostBuffer;
pretendToBeMacIE = _web_findSpoofTableEntry(domain, p - domain) != NULL;
}
}
NSString **userAgentStorage = pretendToBeMacIE
? &_private->userAgentWhenPretendingToBeMacIE : &_private->userAgent;
// Note that we currently don't look at the URL.
// Soon we will spoof different user agent strings for different web pages
// for best results, and that logic will go here.
NSString *userAgent = *userAgentStorage;
if (userAgent) {
return [[userAgent retain] autorelease];
}
// FIXME: Some day we will start reporting the actual CPU here instead of hardcoding PPC.
......@@ -373,16 +404,25 @@ - (NSString *)userAgentForURL:(NSURL *)URL
objectForInfoDictionaryKey:(id)kCFBundleVersionKey];
NSString *applicationName = _private->applicationNameForUserAgent;
NSString *userAgent;
if ([applicationName length]) {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko) %@",
language, sourceVersion, applicationName];
if (pretendToBeMacIE) {
if ([applicationName length]) {
userAgent = [NSString stringWithFormat:@"Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) AppleWebKit/%@ %@",
language, sourceVersion, applicationName];
} else {
userAgent = [NSString stringWithFormat:@"Mozilla/4.0 (compatible; MSIE 5.2; Mac_PowerPC) AppleWebKit/%@",
language, sourceVersion];
}
} else {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko)",
language, sourceVersion];
if ([applicationName length]) {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko) %@",
language, sourceVersion, applicationName];
} else {
userAgent = [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; %@) AppleWebKit/%@ (like Gecko)",
language, sourceVersion];
}
}
_private->userAgent = [userAgent retain];
*userAgentStorage = [userAgent retain];
return userAgent;
}
......
......@@ -31,6 +31,7 @@
NSString *applicationNameForUserAgent;
NSString *userAgentOverride;
NSString *userAgent;
NSString *userAgentWhenPretendingToBeMacIE;
BOOL defersCallbacks;
......
......@@ -65,6 +65,7 @@ - (void)dealloc
[applicationNameForUserAgent release];
[userAgentOverride release];
[userAgent release];
[userAgentWhenPretendingToBeMacIE release];
[controllerSetName release];
[topLevelFrameName release];
......@@ -335,6 +336,8 @@ - (void)_defaultsDidChange
{
[_private->userAgent release];
_private->userAgent = nil;
[_private->userAgentWhenPretendingToBeMacIE release];
_private->userAgentWhenPretendingToBeMacIE = nil;
}
@end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment