1/*
2 * Copyright (C) 2009 Gustavo Noronha Silva
3 * Copyright (C) 2009 Collabora Ltd.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22
23#if USE(SOUP)
24
25#include "ResourceResponse.h"
26
27#include "HTTPHeaderNames.h"
28#include "HTTPParsers.h"
29#include "MIMETypeRegistry.h"
30#include "URLSoup.h"
31#include <wtf/text/CString.h>
32#include <wtf/text/WTFString.h>
33
34namespace WebCore {
35
36void ResourceResponse::updateSoupMessageHeaders(SoupMessageHeaders* soupHeaders) const
37{
38 for (const auto& header : httpHeaderFields())
39 soup_message_headers_append(soupHeaders, header.key.utf8().data(), header.value.utf8().data());
40}
41
42void ResourceResponse::updateFromSoupMessage(SoupMessage* soupMessage)
43{
44 m_url = soupURIToURL(soup_message_get_uri(soupMessage));
45
46 switch (soup_message_get_http_version(soupMessage)) {
47 case SOUP_HTTP_1_0:
48 m_httpVersion = AtomicString("HTTP/1.0", AtomicString::ConstructFromLiteral);
49 break;
50 case SOUP_HTTP_1_1:
51 m_httpVersion = AtomicString("HTTP/1.1", AtomicString::ConstructFromLiteral);
52 break;
53 }
54 m_httpStatusCode = soupMessage->status_code;
55 setHTTPStatusText(soupMessage->reason_phrase);
56
57 m_soupFlags = soup_message_get_flags(soupMessage);
58
59 GTlsCertificate* certificate = 0;
60 soup_message_get_https_status(soupMessage, &certificate, &m_tlsErrors);
61 m_certificate = certificate;
62
63 updateFromSoupMessageHeaders(soupMessage->response_headers);
64}
65
66void ResourceResponse::updateFromSoupMessageHeaders(const SoupMessageHeaders* messageHeaders)
67{
68 SoupMessageHeaders* headers = const_cast<SoupMessageHeaders*>(messageHeaders);
69 SoupMessageHeadersIter headersIter;
70 const char* headerName;
71 const char* headerValue;
72
73 // updateFromSoupMessage could be called several times for the same ResourceResponse object,
74 // thus, we need to clear old header values and update m_httpHeaderFields from soupMessage headers.
75 m_httpHeaderFields.clear();
76
77 soup_message_headers_iter_init(&headersIter, headers);
78 while (soup_message_headers_iter_next(&headersIter, &headerName, &headerValue))
79 addHTTPHeaderField(String(headerName), String(headerValue));
80
81 String contentType;
82 const char* officialType = soup_message_headers_get_one(headers, "Content-Type");
83 if (!m_sniffedContentType.isEmpty() && m_sniffedContentType != officialType)
84 contentType = m_sniffedContentType;
85 else
86 contentType = officialType;
87 setMimeType(extractMIMETypeFromMediaType(contentType));
88 setTextEncodingName(extractCharsetFromMediaType(contentType));
89
90 setExpectedContentLength(soup_message_headers_get_content_length(headers));
91}
92
93CertificateInfo ResourceResponse::platformCertificateInfo() const
94{
95 return CertificateInfo(m_certificate.get(), m_tlsErrors);
96}
97
98String ResourceResponse::platformSuggestedFilename() const
99{
100 String contentDisposition(httpHeaderField(HTTPHeaderName::ContentDisposition));
101 if (contentDisposition.isEmpty())
102 return String();
103
104 if (contentDisposition.is8Bit())
105 contentDisposition = String::fromUTF8WithLatin1Fallback(contentDisposition.characters8(), contentDisposition.length());
106 SoupMessageHeaders* soupHeaders = soup_message_headers_new(SOUP_MESSAGE_HEADERS_RESPONSE);
107 soup_message_headers_append(soupHeaders, "Content-Disposition", contentDisposition.utf8().data());
108 GRefPtr<GHashTable> params;
109 soup_message_headers_get_content_disposition(soupHeaders, nullptr, &params.outPtr());
110 soup_message_headers_free(soupHeaders);
111 char* filename = params ? static_cast<char*>(g_hash_table_lookup(params.get(), "filename")) : nullptr;
112 return filename ? String::fromUTF8(filename) : String();
113}
114
115}
116
117#endif
118