1 /*
2 * Copyright (C) 2004, 2006, 2007, 2008 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 "ResourceHandle.h"
28 #include "ResourceHandleInternal.h"
29
30 #include "Logging.h"
31 #include "ResourceHandleClient.h"
32 #include "Timer.h"
33 #include <algorithm>
34
35 namespace WebCore {
36
37 static bool shouldForceContentSniffing;
38
39 static bool portAllowed(const ResourceRequest&);
40
ResourceHandle(const ResourceRequest & request,ResourceHandleClient * client,bool defersLoading,bool shouldContentSniff,bool mightDownloadFromHandle)41 ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading,
42 bool shouldContentSniff, bool mightDownloadFromHandle)
43 : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle))
44 {
45 }
46
create(const ResourceRequest & request,ResourceHandleClient * client,Frame * frame,bool defersLoading,bool shouldContentSniff,bool mightDownloadFromHandle)47 PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client,
48 Frame* frame, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle)
49 {
50 if (shouldContentSniff)
51 shouldContentSniff = shouldContentSniffURL(request.url());
52
53 RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle)));
54
55 if (!request.url().isValid()) {
56 newHandle->scheduleFailure(InvalidURLFailure);
57 return newHandle.release();
58 }
59
60 if (!portAllowed(request)) {
61 newHandle->scheduleFailure(BlockedFailure);
62 return newHandle.release();
63 }
64
65 if (newHandle->start(frame))
66 return newHandle.release();
67
68 return 0;
69 }
70
scheduleFailure(FailureType type)71 void ResourceHandle::scheduleFailure(FailureType type)
72 {
73 d->m_failureType = type;
74 d->m_failureTimer.startOneShot(0);
75 }
76
fireFailure(Timer<ResourceHandle> *)77 void ResourceHandle::fireFailure(Timer<ResourceHandle>*)
78 {
79 if (!client())
80 return;
81
82 switch (d->m_failureType) {
83 case BlockedFailure:
84 client()->wasBlocked(this);
85 return;
86 case InvalidURLFailure:
87 client()->cannotShowURL(this);
88 return;
89 }
90
91 ASSERT_NOT_REACHED();
92 }
93
client() const94 ResourceHandleClient* ResourceHandle::client() const
95 {
96 return d->m_client;
97 }
98
setClient(ResourceHandleClient * client)99 void ResourceHandle::setClient(ResourceHandleClient* client)
100 {
101 d->m_client = client;
102 }
103
request() const104 const ResourceRequest& ResourceHandle::request() const
105 {
106 return d->m_request;
107 }
108
clearAuthentication()109 void ResourceHandle::clearAuthentication()
110 {
111 #if PLATFORM(MAC)
112 d->m_currentMacChallenge = nil;
113 #elif USE(CFNETWORK)
114 d->m_currentCFChallenge = 0;
115 #endif
116 d->m_currentWebChallenge.nullify();
117 }
118
portAllowed(const ResourceRequest & request)119 static bool portAllowed(const ResourceRequest& request)
120 {
121 unsigned short port = request.url().port();
122
123 // Since most URLs don't have a port, return early for the "no port" case.
124 if (!port)
125 return true;
126
127 // This blocked port list matches the port blocking that Mozilla implements.
128 // See http://www.mozilla.org/projects/netlib/PortBanning.html for more information.
129 static const unsigned short blockedPortList[] = {
130 1, // tcpmux
131 7, // echo
132 9, // discard
133 11, // systat
134 13, // daytime
135 15, // netstat
136 17, // qotd
137 19, // chargen
138 20, // FTP-data
139 21, // FTP-control
140 22, // SSH
141 23, // telnet
142 25, // SMTP
143 37, // time
144 42, // name
145 43, // nicname
146 53, // domain
147 77, // priv-rjs
148 79, // finger
149 87, // ttylink
150 95, // supdup
151 101, // hostriame
152 102, // iso-tsap
153 103, // gppitnp
154 104, // acr-nema
155 109, // POP2
156 110, // POP3
157 111, // sunrpc
158 113, // auth
159 115, // SFTP
160 117, // uucp-path
161 119, // nntp
162 123, // NTP
163 135, // loc-srv / epmap
164 139, // netbios
165 143, // IMAP2
166 179, // BGP
167 389, // LDAP
168 465, // SMTP+SSL
169 512, // print / exec
170 513, // login
171 514, // shell
172 515, // printer
173 526, // tempo
174 530, // courier
175 531, // Chat
176 532, // netnews
177 540, // UUCP
178 556, // remotefs
179 563, // NNTP+SSL
180 587, // ESMTP
181 601, // syslog-conn
182 636, // LDAP+SSL
183 993, // IMAP+SSL
184 995, // POP3+SSL
185 2049, // NFS
186 3659, // apple-sasl / PasswordServer [Apple addition]
187 4045, // lockd
188 6000, // X11
189 };
190 const unsigned short* const blockedPortListEnd = blockedPortList
191 + sizeof(blockedPortList) / sizeof(blockedPortList[0]);
192
193 // If the port is not in the blocked port list, allow it.
194 if (!std::binary_search(blockedPortList, blockedPortListEnd, port))
195 return true;
196
197 // Allow ports 21 and 22 for FTP URLs, as Mozilla does.
198 if ((port == 21 || port == 22) && request.url().protocolIs("ftp"))
199 return true;
200
201 // Allow any port number in a file URL, since the port number is ignored.
202 if (request.url().protocolIs("file"))
203 return true;
204
205 return false;
206 }
207
shouldContentSniff() const208 bool ResourceHandle::shouldContentSniff() const
209 {
210 return d->m_shouldContentSniff;
211 }
212
shouldContentSniffURL(const KURL & url)213 bool ResourceHandle::shouldContentSniffURL(const KURL& url)
214 {
215 #if PLATFORM(MAC)
216 if (shouldForceContentSniffing)
217 return true;
218 #endif
219 // We shouldn't content sniff file URLs as their MIME type should be established via their extension.
220 return !url.protocolIs("file");
221 }
222
forceContentSniffing()223 void ResourceHandle::forceContentSniffing()
224 {
225 shouldForceContentSniffing = true;
226 }
227
228 } // namespace WebCore
229