: O. Yuanying

Safari のリファラを変更したい

FC2 のブログとかを Google Reader や LDR で読むと画像が表示されなくてヒジョーにストレスを感じる。

ほんと死んじまえ!って感じでブログを書くならFC2はやめてほしいけど、 そんな非現実的なことを呻いていても仕方ないので Safari のリファラをなんとかいじってみようと調べてみる。

ってか Firefox 使いなら RefControl :: Firefox Add-ons があるので Firefox にしとけばいいじゃんって話なんだけど。ここは Safariで。

NSURLDownload + NSURLRequest

HMDTの本、

とか読む限り、WebKit はリソースのリクエストに NSURLRequest を使うらしい。

それならば話は簡単だ!と思ったのはちょっと軽率だったが、まあとりあえずこんな努力をしてみた。


@implementation NSURLRequest (SRHSwizzle)
-(NSDictionary *) _srh_allHTTPHeaderFields
{
    NSMutableDictionary* headers = [NSMutableDictionary 
        dictionaryWithDictionary:[self _srh_allHTTPHeaderFields]
    ];
    [headers setValue:@"http://www.google.com/" forKey:@"Referer"];
    return headers;
}
@end

@implementation SRHSafariReferrerHack
+ (void) load
{
    BOOL rc;
    rc = MethodSwizzle(
        [NSURLRequest class], 
        @selector(allHTTPHeaderFields), 
        @selector(_srh_allHTTPHeaderFields)
    );
}
@end

Referrer として必ず "http://www.google.com/" を返す _srh_allHTTPHeaderFields というメソッドを NSURLRequestに用意してやって、 allHTTPHeaderFields と MethodSwizzling。

これを SIMBL プラグインとして Safari に読み込ませてやった。

が、駄目。

自分の鯖にアクセスしてみたらこんなログを残した。

0.238.74.67 - - [16/Jun/2008:12:11:40 +0900] "GET / HTTP/1.1" 200 27161 "http://www.google.com/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_3; en-us) AppleWebKit/525.18 (KHTML, like Gecko)"
60.238.74.67 - - [16/Jun/2008:12:11:41 +0900] "GET /images/banner.png?1208240823 HTTP/1.1" 200 2192 "http://yuanying.oeilvert.org/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_3; en-us) AppleWebKit/525.18 (KHTML, like Gecko)"

直のアクセスのリファラは変わったんだけど、そのHTMLから読み込まれる画像とかのリファラは変わってない。

webView:resource:willSendRequest:redirectResponse:fromDataSource: が送られてくる時点のヘッダはちゃんと置き換わってるから、 実際にリソースをダウンロードする時点でリファラをちゃんと直してるっぽい。

WebKit のソースを読む

こうなったらもう絶対ハックしてやる!っていう勢いで、 WebKit のソースをダウンロードして読み始める。

WebFrame.mm

WebFrame.mm の 1196行目あたりにドキュメント中のリソースを読み込んでるらしきソースを発見する。


- (void)loadRequest:(NSURLRequest *)request
{
    _private->coreFrame->loader()->load(request);
}

えーっと。。。WebCore に潜れとおっしゃりますか?

ハックできそう

WebCore 読んでたら、結局のところリソースのダウンロードは NSURLConnection を使うってところに行き着いた。

とりあえず簡単に試してみようと、NSURLConnection をポージング。


@implementation SRHNSURLConnection
+ (void)load
{
    [self poseAsClass:[NSURLConnection class]];
        NSLog(@"NSURLConnection is overridded.");
}

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate
{
        NSMutableURLRequest* newRequest = [NSMutableURLRequest requestWithURL:[request URL]];
        [newRequest setCachePolicy:[request cachePolicy]];
        [newRequest setTimeoutInterval:[request timeoutInterval]];
        [newRequest setAllHTTPHeaderFields:[request allHTTPHeaderFields]];
        [newRequest setHTTPMethod:[request HTTPMethod]];
        [newRequest setValue:@"http://www.bonnoh.org/" forHTTPHeaderField:@"Referer"];
        
    self = [super initWithRequest:newRequest delegate:delegate];
    return self;
}
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately
{
        NSMutableURLRequest* newRequest = [NSMutableURLRequest requestWithURL:[request URL]];
        [newRequest setCachePolicy:[request cachePolicy]];
        [newRequest setTimeoutInterval:[request timeoutInterval]];
        [newRequest setAllHTTPHeaderFields:[request allHTTPHeaderFields]];
        [newRequest setHTTPMethod:[request HTTPMethod]];
        [newRequest setValue:@"http://www.bonnoh.org/" forHTTPHeaderField:@"Referer"];

    self =[super initWithRequest:newRequest delegate:delegate startImmediately:startImmediately];
    return self;
}
@end

うまくいきましたよ、奥さん!

報告

Safari でリファラをいじるSIMBLプラグインをリリースしました。