1/* 2 * Copyright (C) 2006 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 "ResourceResponse.h" 28 29#if !USE(CFNETWORK) 30 31#import "HTTPParsers.h" 32#import "WebCoreURLResponse.h" 33#import "WebCoreSystemInterface.h" 34#import <Foundation/Foundation.h> 35#import <wtf/StdLibExtras.h> 36#import <limits> 37#include <wtf/text/CString.h> 38 39@interface NSURLResponse (FoundationSecretsWebCoreKnowsAbout) 40- (NSTimeInterval)_calculatedExpiration; 41@end 42 43#ifdef BUILDING_ON_TIGER 44typedef int NSInteger; 45#endif 46 47namespace WebCore { 48 49static NSString* const commonHeaderFields[] = { 50 @"Age", @"Cache-Control", @"Date", @"Etag", @"Expires", @"Last-Modified", @"Pragma" 51}; 52static const int numCommonHeaderFields = sizeof(commonHeaderFields) / sizeof(AtomicString*); 53 54NSURLResponse *ResourceResponse::nsURLResponse() const 55{ 56 if (!m_nsResponse && !m_isNull) { 57 // Work around a mistake in the NSURLResponse class. 58 // The init function takes an NSInteger, even though the accessor returns a long long. 59 // For values that won't fit in an NSInteger, pass -1 instead. 60 NSInteger expectedContentLength; 61 if (m_expectedContentLength < 0 || m_expectedContentLength > std::numeric_limits<NSInteger>::max()) 62 expectedContentLength = -1; 63 else 64 expectedContentLength = static_cast<NSInteger>(m_expectedContentLength); 65 const_cast<ResourceResponse*>(this)->m_nsResponse.adoptNS([[NSURLResponse alloc] initWithURL:m_url MIMEType:m_mimeType expectedContentLength:expectedContentLength textEncodingName:m_textEncodingName]); 66 } 67 return m_nsResponse.get(); 68} 69 70void ResourceResponse::platformLazyInit(InitLevel initLevel) 71{ 72 if (m_initLevel >= initLevel) 73 return; 74 75 if (m_isNull) { 76 ASSERT(!m_nsResponse); 77 return; 78 } 79 80 if (m_initLevel < CommonFieldsOnly && initLevel >= CommonFieldsOnly) { 81 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 82 83 m_httpHeaderFields.clear(); 84 m_url = [m_nsResponse.get() URL]; 85 m_mimeType = [m_nsResponse.get() MIMEType]; 86 m_expectedContentLength = [m_nsResponse.get() expectedContentLength]; 87 m_textEncodingName = [m_nsResponse.get() textEncodingName]; 88 89 // Workaround for <rdar://problem/8757088>, can be removed once that is fixed. 90 unsigned textEncodingNameLength = m_textEncodingName.length(); 91 if (textEncodingNameLength >= 2 && m_textEncodingName[0U] == '"' && m_textEncodingName[textEncodingNameLength - 1] == '"') 92 m_textEncodingName = m_textEncodingName.substring(1, textEncodingNameLength - 2); 93 94 m_suggestedFilename = [m_nsResponse.get() suggestedFilename]; 95 96 if ([m_nsResponse.get() isKindOfClass:[NSHTTPURLResponse class]]) { 97 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)m_nsResponse.get(); 98 99 m_httpStatusCode = [httpResponse statusCode]; 100 101 NSDictionary *headers = [httpResponse allHeaderFields]; 102 103 for (int i = 0; i < numCommonHeaderFields; i++) { 104 if (NSString* headerValue = [headers objectForKey:commonHeaderFields[i]]) 105 m_httpHeaderFields.set([commonHeaderFields[i] UTF8String], headerValue); 106 } 107 } else 108 m_httpStatusCode = 0; 109 110 [pool drain]; 111 } 112 113 if (m_initLevel < AllFields && initLevel >= AllFields && [m_nsResponse.get() isKindOfClass:[NSHTTPURLResponse class]]) { 114 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 115 116 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)m_nsResponse.get(); 117 118 RetainPtr<NSString> httpStatusLine(AdoptNS, wkCopyNSURLResponseStatusLine(m_nsResponse.get())); 119 if (httpStatusLine) 120 m_httpStatusText = extractReasonPhraseFromHTTPStatusLine(httpStatusLine.get()); 121 else 122 m_httpStatusText = "OK"; 123 124 NSDictionary *headers = [httpResponse allHeaderFields]; 125 NSEnumerator *e = [headers keyEnumerator]; 126 while (NSString *name = [e nextObject]) 127 m_httpHeaderFields.set(name, [headers objectForKey:name]); 128 129 [pool drain]; 130 } 131 132 m_initLevel = initLevel; 133} 134 135 136bool ResourceResponse::platformCompare(const ResourceResponse& a, const ResourceResponse& b) 137{ 138 return a.nsURLResponse() == b.nsURLResponse(); 139} 140 141} // namespace WebCore 142 143#endif // !USE(CFNETWORK) 144