// AIFacebookXMPPOAuthWebViewWindowController.m // Created by Colin Barrett on 11/19/10. // Copyright 2010 __MyCompanyName__. All rights reserved. #import "AIFacebookXMPPOAuthWebViewWindowController.h" #import "AIFacebookXMPPAccountViewController.h" #import "AIFacebookXMPPAccount.h" @interface AIFacebookXMPPOAuthWebViewWindowController () - (void)addCookiesFromResponse:(NSHTTPURLResponse *)response; - (void)addCookiesToRequest:(NSMutableURLRequest *)request; @implementation AIFacebookXMPPOAuthWebViewWindowController @synthesize webView, spinner; @synthesize autoFillPassword, autoFillUsername; if ((self = [super initWithWindowNibName:@"AIFacebookXMPPOauthWebViewWindow"])) { self.cookies = [[[NSMutableDictionary alloc] init] autorelease]; - (NSString *)adiumFrameAutosaveName return @"Facebook OAuth Window Frame"; - (void)showWindow:(id)sender [super showWindow:sender]; [webView setMainFrameURL:@"https://graph.facebook.com/oauth/authorize?" @"client_id=" ADIUM_APP_ID "&" @"redirect_uri=http%3A%2F%2Fwww.facebook.com%2Fconnect%2Flogin_success.html&" @"scope=xmpp_login,offline_access&" [spinner startAnimation:self]; [self.window setTitle:AILocalizedString(@"Facebook Account Setup", nil)]; - (void)windowWillClose:(id)sender [super windowWillClose:sender]; /* The user closed; notify the account of failure */ [self.account oAuthWebViewControllerDidFail:self]; - (NSDictionary*)parseURLParams:(NSString *)query { NSArray *pairs = [query componentsSeparatedByString:@"&"]; NSMutableDictionary *params = [[[NSMutableDictionary alloc] init] autorelease]; for (NSString *pair in pairs) { NSArray *kv = [pair componentsSeparatedByString:@"="]; NSString *val = [[kv objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; [params setObject:val forKey:[kv objectAtIndex:0]]; - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame [spinner startAnimation:self]; - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame if ([sender mainFrame] == frame) { [spinner stopAnimation:self]; if ([frame.dataSource.request.URL.host isEqual:@"www.facebook.com"] && [frame.dataSource.request.URL.path isEqual:@"/login.php"]) { DOMDocument *domDoc = [frame DOMDocument]; NSString *text = domDoc.body.innerHTML; text = [text stringByReplacingOccurrencesOfString:@"Log in to use your Facebook account" withString:@"The new version of Adium has a much more reliable Facebook Chat service. Log in to use your Facebook account"]; domDoc.body.innerHTML = text; [[domDoc getElementById:@"email"] setValue:self.autoFillUsername]; [[domDoc getElementById:@"pass"] setValue:self.autoFillPassword]; DOMElement *checkbox = [domDoc getElementById:@"persistent_inputcheckbox"]; if ([checkbox isKindOfClass:[NSClassFromString(@"DOMHTMLInputElement") class]] && [checkbox respondsToSelector:@selector(setChecked:)]) { [((DOMHTMLInputElement *)checkbox) setChecked:YES]; - (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource; [self addCookiesFromResponse:(id)redirectResponse]; NSMutableURLRequest *mutableRequest = [[request mutableCopy] autorelease]; [mutableRequest setHTTPShouldHandleCookies:NO]; [self addCookiesToRequest:mutableRequest]; if ([[[mutableRequest URL] host] isEqual:@"www.facebook.com"] && [[[mutableRequest URL] path] isEqual:@"/connect/login_success.html"]) { NSDictionary *urlParamDict = [self parseURLParams:[[mutableRequest URL] fragment]]; NSString *token = [urlParamDict objectForKey:@"access_token"]; if (token && ![token isEqualToString:@""]) { [self.account oAuthWebViewController:self didSucceedWithToken:token]; /* Got a bad token, or the user canceled */ [self.account oAuthWebViewControllerDidFail:self]; - (void)webView:(WebView *)sender resource:(id)identifier didReceiveResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource; if ([response isKindOfClass:[NSHTTPURLResponse class]]) { [self addCookiesFromResponse:(NSHTTPURLResponse *)response]; - (void)addCookiesFromResponse:(NSHTTPURLResponse *)response NSArray *newCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[response URL]]; for (NSHTTPCookie *newCookie in newCookies) { [cookies setObject:newCookie forKey:newCookie.name]; - (void)addCookiesToRequest:(NSMutableURLRequest *)request NSURL *requestURL = [request URL]; NSMutableArray *sentCookies = [NSMutableArray array]; // same origin: domain, port, path. for (NSHTTPCookie *cookie in cookies.allValues) { if ([[cookie expiresDate] timeIntervalSinceNow] < 0) { if ([cookie isSecure] && ![[requestURL scheme] isEqualToString:@"https"]) { if ([[cookie domain] hasPrefix:@"."]) { // ".example.com" should match "foo.example.com" and "example.com" if (!([[requestURL host] hasSuffix:[cookie domain]] || [[@"." stringByAppendingString:[requestURL host]] isEqualToString:[cookie domain]])) { if (![[requestURL host] isEqualToString:[cookie domain]]) { if ([[cookie portList] count] && ([requestURL port] != NULL) && ![[cookie portList] containsObject:[requestURL port]]) { if (![[requestURL path] hasPrefix:[cookie path]]) { [sentCookies addObject:cookie]; NSMutableDictionary *headers = [[[request allHTTPHeaderFields] mutableCopy] autorelease]; [headers setValuesForKeysWithDictionary:[NSHTTPCookie requestHeaderFieldsWithCookies:sentCookies]]; [request setAllHTTPHeaderFields:headers];