[Soup] utilize multipart/x-mixed-replace support recently added to libsoup
[WebKit-https.git] / Source / WebCore / platform / network / soup / ResourceResponseSoup.cpp
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 #include "ResourceResponse.h"
23
24 #include <wtf/gobject/GOwnPtr.h>
25 #include "HTTPParsers.h"
26 #include "MIMETypeRegistry.h"
27 #include "SoupURIUtils.h"
28 #include <wtf/text/CString.h>
29 #include <wtf/text/StringBuilder.h>
30 #include <wtf/text/WTFString.h>
31
32 using namespace std;
33
34 namespace WebCore {
35
36 SoupMessage* ResourceResponse::toSoupMessage() const
37 {
38     // This GET here is just because SoupMessage wants it, we dn't really know.
39     SoupMessage* soupMessage = soup_message_new("GET", url().string().utf8().data());
40     if (!soupMessage)
41         return 0;
42
43     soupMessage->status_code = httpStatusCode();
44
45     const HTTPHeaderMap& headers = httpHeaderFields();
46     SoupMessageHeaders* soupHeaders = soupMessage->response_headers;
47     if (!headers.isEmpty()) {
48         HTTPHeaderMap::const_iterator end = headers.end();
49         for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
50             soup_message_headers_append(soupHeaders, it->key.string().utf8().data(), it->value.utf8().data());
51     }
52
53     soup_message_set_flags(soupMessage, m_soupFlags);
54
55     g_object_set(G_OBJECT(soupMessage), "tls-certificate", m_certificate.get(), "tls-errors", m_tlsErrors, NULL);
56
57     // Body data is not in the message.
58     return soupMessage;
59 }
60
61 void ResourceResponse::updateFromSoupMessage(SoupMessage* soupMessage)
62 {
63     m_url = soupURIToKURL(soup_message_get_uri(soupMessage));
64
65     m_httpStatusCode = soupMessage->status_code;
66     setHTTPStatusText(soupMessage->reason_phrase);
67
68     m_soupFlags = soup_message_get_flags(soupMessage);
69
70     GTlsCertificate* certificate = 0;
71     soup_message_get_https_status(soupMessage, &certificate, &m_tlsErrors);
72     m_certificate = certificate;
73
74     updateFromSoupMessageHeaders(soupMessage->response_headers);
75 }
76
77 void ResourceResponse::updateFromSoupMessageHeaders(const SoupMessageHeaders* messageHeaders)
78 {
79     SoupMessageHeaders* headers = const_cast<SoupMessageHeaders*>(messageHeaders);
80     SoupMessageHeadersIter headersIter;
81     const char* headerName;
82     const char* headerValue;
83
84     // updateFromSoupMessage could be called several times for the same ResourceResponse object,
85     // thus, we need to clear old header values and update m_httpHeaderFields from soupMessage headers.
86     m_httpHeaderFields.clear();
87
88     soup_message_headers_iter_init(&headersIter, headers);
89     while (soup_message_headers_iter_next(&headersIter, &headerName, &headerValue)) {
90         String headerNameString = String::fromUTF8WithLatin1Fallback(headerName, strlen(headerName));
91         HTTPHeaderMap::const_iterator it = m_httpHeaderFields.find(headerNameString);
92         if (it == m_httpHeaderFields.end() || (it != m_httpHeaderFields.end() && it->value.isEmpty()))
93             m_httpHeaderFields.set(headerNameString, String::fromUTF8WithLatin1Fallback(headerValue, strlen(headerValue)));
94         else {
95             StringBuilder builder;
96             builder.append(it->value);
97             builder.appendLiteral(", ");
98             builder.append(String::fromUTF8WithLatin1Fallback(headerValue, strlen(headerValue)));
99             m_httpHeaderFields.set(headerNameString, builder.toString());
100         }
101     }
102
103     String contentType;
104     const char* officialType = soup_message_headers_get_one(headers, "Content-Type");
105     if (!m_sniffedContentType.isEmpty() && m_sniffedContentType != officialType)
106         contentType = m_sniffedContentType;
107     else
108         contentType = officialType;
109     setMimeType(extractMIMETypeFromMediaType(contentType));
110     setTextEncodingName(extractCharsetFromMediaType(contentType));
111
112     setExpectedContentLength(soup_message_headers_get_content_length(headers));
113     setSuggestedFilename(filenameFromHTTPContentDisposition(httpHeaderField("Content-Disposition")));}
114
115 }