1 /* 2 * Copyright (C) 2006, 2007 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 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 #include "config.h" 27 #include "ResourceResponse.h" 28 29 #include "HTTPParsers.h" 30 #include "MIMETypeRegistry.h" 31 #include <CFNetwork/CFURLResponsePriv.h> 32 #include <wtf/RetainPtr.h> 33 34 using namespace std; 35 36 // We would like a better value for a maximum time_t, 37 // but there is no way to do that in C with any certainty. 38 // INT_MAX should work well enough for our purposes. 39 #define MAX_TIME_T ((time_t)INT_MAX) 40 41 namespace WebCore { 42 43 CFURLResponseRef ResourceResponse::cfURLResponse() const 44 { 45 return m_cfResponse.get(); 46 } 47 48 static inline bool filenameHasSaneExtension(const String& filename) 49 { 50 int dot = filename.find('.'); 51 52 // The dot can't be the first or last character in the filename. 53 int length = filename.length(); 54 return dot > 0 && dot < length - 1; 55 } 56 57 static time_t toTimeT(CFAbsoluteTime time) 58 { 59 static const double maxTimeAsDouble = std::numeric_limits<time_t>::max(); 60 static const double minTimeAsDouble = std::numeric_limits<time_t>::min(); 61 return min(max(minTimeAsDouble, time + kCFAbsoluteTimeIntervalSince1970), maxTimeAsDouble); 62 } 63 64 void ResourceResponse::platformLazyInit() 65 { 66 if (m_isUpToDate) 67 return; 68 m_isUpToDate = true; 69 70 if (m_isNull) { 71 ASSERT(!m_cfResponse.get()); 72 return; 73 } 74 75 // FIXME: We may need to do MIME type sniffing here (unless that is done in CFURLResponseGetMIMEType). 76 77 m_url = CFURLResponseGetURL(m_cfResponse.get()); 78 m_mimeType = CFURLResponseGetMIMEType(m_cfResponse.get()); 79 m_expectedContentLength = CFURLResponseGetExpectedContentLength(m_cfResponse.get()); 80 m_textEncodingName = CFURLResponseGetTextEncodingName(m_cfResponse.get()); 81 82 m_lastModifiedDate = toTimeT(CFURLResponseGetLastModifiedDate(m_cfResponse.get())); 83 84 RetainPtr<CFStringRef> suggestedFilename(AdoptCF, CFURLResponseCopySuggestedFilename(m_cfResponse.get())); 85 m_suggestedFilename = suggestedFilename.get(); 86 87 CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(m_cfResponse.get()); 88 if (httpResponse) { 89 m_httpStatusCode = CFHTTPMessageGetResponseStatusCode(httpResponse); 90 91 RetainPtr<CFStringRef> statusLine(AdoptCF, CFHTTPMessageCopyResponseStatusLine(httpResponse)); 92 String statusText(statusLine.get()); 93 int spacePos = statusText.find(' '); 94 // Remove the status code from the status text. 95 spacePos = statusText.find(' ', spacePos + 1); 96 statusText = statusText.substring(spacePos + 1); 97 98 m_httpStatusText = statusText; 99 100 RetainPtr<CFDictionaryRef> headers(AdoptCF, CFHTTPMessageCopyAllHeaderFields(httpResponse)); 101 CFIndex headerCount = CFDictionaryGetCount(headers.get()); 102 Vector<const void*, 128> keys(headerCount); 103 Vector<const void*, 128> values(headerCount); 104 CFDictionaryGetKeysAndValues(headers.get(), keys.data(), values.data()); 105 for (int i = 0; i < headerCount; ++i) 106 m_httpHeaderFields.set((CFStringRef)keys[i], (CFStringRef)values[i]); 107 } else 108 m_httpStatusCode = 0; 109 } 110 111 bool ResourceResponse::platformCompare(const ResourceResponse& a, const ResourceResponse& b) 112 { 113 return CFEqual(a.cfURLResponse(), b.cfURLResponse()); 114 } 115 116 117 } 118