1/* 2 * Copyright (C) 2003, 2006, 2008, 2012 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "PlatformCookieJar.h" 28 29#if !USE(CFNETWORK) 30 31#import "BlockExceptions.h" 32#import "Cookie.h" 33#import "CookieStorage.h" 34#import "URL.h" 35#import "NetworkStorageSession.h" 36#import "WebCoreSystemInterface.h" 37 38enum { 39 NSHTTPCookieAcceptPolicyExclusivelyFromMainDocumentDomain = 3 40}; 41 42@interface NSHTTPCookieStorage (Details) 43- (void)removeCookiesSinceDate:(NSDate *)date; 44@end 45 46namespace WebCore { 47 48static RetainPtr<NSArray> filterCookies(NSArray *unfilteredCookies) 49{ 50 NSUInteger count = [unfilteredCookies count]; 51 RetainPtr<NSMutableArray> filteredCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:count]); 52 53 for (NSUInteger i = 0; i < count; ++i) { 54 NSHTTPCookie *cookie = (NSHTTPCookie *)[unfilteredCookies objectAtIndex:i]; 55 56 // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie, 57 // which would be sent as "Cookie: =". We have a workaround in setCookies() to prevent 58 // that, but we also need to avoid sending cookies that were previously stored, and 59 // there's no harm to doing this check because such a cookie is never valid. 60 if (![[cookie name] length]) 61 continue; 62 63 if ([cookie isHTTPOnly]) 64 continue; 65 66 [filteredCookies.get() addObject:cookie]; 67 } 68 69 return filteredCookies; 70} 71 72String cookiesForDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url) 73{ 74 BEGIN_BLOCK_OBJC_EXCEPTIONS; 75 76 NSArray *cookies = wkHTTPCookiesForURL(session.cookieStorage().get(), firstParty, url); 77 return [[NSHTTPCookie requestHeaderFieldsWithCookies:filterCookies(cookies).get()] objectForKey:@"Cookie"]; 78 79 END_BLOCK_OBJC_EXCEPTIONS; 80 return String(); 81} 82 83String cookieRequestHeaderFieldValue(const NetworkStorageSession& session, const URL& firstParty, const URL& url) 84{ 85 BEGIN_BLOCK_OBJC_EXCEPTIONS; 86 87 NSArray *cookies = wkHTTPCookiesForURL(session.cookieStorage().get(), firstParty, url); 88 return [[NSHTTPCookie requestHeaderFieldsWithCookies:cookies] objectForKey:@"Cookie"]; 89 90 END_BLOCK_OBJC_EXCEPTIONS; 91 return String(); 92} 93 94void setCookiesFromDOM(const NetworkStorageSession& session, const URL& firstParty, const URL& url, const String& cookieStr) 95{ 96 BEGIN_BLOCK_OBJC_EXCEPTIONS; 97 98 // <rdar://problem/5632883> On 10.5, NSHTTPCookieStorage would store an empty cookie, 99 // which would be sent as "Cookie: =". 100 if (cookieStr.isEmpty()) 101 return; 102 103 // <http://bugs.webkit.org/show_bug.cgi?id=6531>, <rdar://4409034> 104 // cookiesWithResponseHeaderFields doesn't parse cookies without a value 105 String cookieString = cookieStr.contains('=') ? cookieStr : cookieStr + "="; 106 107 NSURL *cookieURL = url; 108 RetainPtr<NSArray> filteredCookies = filterCookies([NSHTTPCookie cookiesWithResponseHeaderFields:[NSDictionary dictionaryWithObject:cookieString forKey:@"Set-Cookie"] forURL:cookieURL]); 109 ASSERT([filteredCookies.get() count] <= 1); 110 111 wkSetHTTPCookiesForURL(session.cookieStorage().get(), filteredCookies.get(), cookieURL, firstParty); 112 113 END_BLOCK_OBJC_EXCEPTIONS; 114} 115 116bool cookiesEnabled(const NetworkStorageSession& session, const URL& /*firstParty*/, const URL& /*url*/) 117{ 118 BEGIN_BLOCK_OBJC_EXCEPTIONS; 119 120 NSHTTPCookieAcceptPolicy cookieAcceptPolicy = static_cast<NSHTTPCookieAcceptPolicy>(wkGetHTTPCookieAcceptPolicy(session.cookieStorage().get())); 121 return cookieAcceptPolicy == NSHTTPCookieAcceptPolicyAlways || cookieAcceptPolicy == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain || cookieAcceptPolicy == NSHTTPCookieAcceptPolicyExclusivelyFromMainDocumentDomain; 122 123 END_BLOCK_OBJC_EXCEPTIONS; 124 return false; 125} 126 127bool getRawCookies(const NetworkStorageSession& session, const URL& firstParty, const URL& url, Vector<Cookie>& rawCookies) 128{ 129 rawCookies.clear(); 130 BEGIN_BLOCK_OBJC_EXCEPTIONS; 131 132 NSArray *cookies = wkHTTPCookiesForURL(session.cookieStorage().get(), firstParty, url); 133 NSUInteger count = [cookies count]; 134 rawCookies.reserveCapacity(count); 135 for (NSUInteger i = 0; i < count; ++i) { 136 NSHTTPCookie *cookie = (NSHTTPCookie *)[cookies objectAtIndex:i]; 137 NSTimeInterval expires = [[cookie expiresDate] timeIntervalSince1970] * 1000; 138 rawCookies.uncheckedAppend(Cookie([cookie name], [cookie value], [cookie domain], [cookie path], expires, 139 [cookie isHTTPOnly], [cookie isSecure], [cookie isSessionOnly])); 140 } 141 142 END_BLOCK_OBJC_EXCEPTIONS; 143 return true; 144} 145 146void deleteCookie(const NetworkStorageSession& session, const URL& url, const String& cookieName) 147{ 148 BEGIN_BLOCK_OBJC_EXCEPTIONS; 149 150 RetainPtr<CFHTTPCookieStorageRef> cookieStorage = session.cookieStorage(); 151 NSArray *cookies = wkHTTPCookiesForURL(cookieStorage.get(), 0, url); 152 153 NSString *cookieNameString = cookieName; 154 155 NSUInteger count = [cookies count]; 156 for (NSUInteger i = 0; i < count; ++i) { 157 NSHTTPCookie *cookie = (NSHTTPCookie *)[cookies objectAtIndex:i]; 158 if ([[cookie name] isEqualToString:cookieNameString]) 159 wkDeleteHTTPCookie(cookieStorage.get(), cookie); 160 } 161 162 END_BLOCK_OBJC_EXCEPTIONS; 163} 164 165void getHostnamesWithCookies(const NetworkStorageSession& session, HashSet<String>& hostnames) 166{ 167 BEGIN_BLOCK_OBJC_EXCEPTIONS; 168 169 NSArray *cookies = wkHTTPCookies(session.cookieStorage().get()); 170 171 for (NSHTTPCookie* cookie in cookies) 172 hostnames.add([cookie domain]); 173 174 END_BLOCK_OBJC_EXCEPTIONS; 175} 176 177void deleteCookiesForHostname(const NetworkStorageSession& session, const String& hostname) 178{ 179 BEGIN_BLOCK_OBJC_EXCEPTIONS; 180 181 RetainPtr<CFHTTPCookieStorageRef> cookieStorage = session.cookieStorage(); 182 NSArray *cookies = wkHTTPCookies(cookieStorage.get()); 183 if (!cookies) 184 return; 185 186 for (NSHTTPCookie* cookie in cookies) { 187 if (hostname == String([cookie domain])) 188 wkDeleteHTTPCookie(cookieStorage.get(), cookie); 189 } 190 191 END_BLOCK_OBJC_EXCEPTIONS; 192} 193 194void deleteAllCookies(const NetworkStorageSession& session) 195{ 196 wkDeleteAllHTTPCookies(session.cookieStorage().get()); 197} 198 199void deleteAllCookiesModifiedAfterDate(const NetworkStorageSession& session, double date) 200{ 201 UNUSED_PARAM(session); 202 203 NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; 204 if ([cookieStorage respondsToSelector:@selector(removeCookiesSinceDate:)]) 205 [cookieStorage removeCookiesSinceDate:[NSDate dateWithTimeIntervalSince1970:date]]; 206} 207 208} 209 210#endif // !USE(CFNETWORK) 211