d3ab582b4a84a97cfc384d9e0a3ab2ce2d0f47ec
[WebKit-https.git] / WebCore / platform / network / ResourceHandle.cpp
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
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
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
71 void ResourceHandle::scheduleFailure(FailureType type)
72 {
73     d->m_failureType = type;
74     d->m_failureTimer.startOneShot(0);
75 }
76
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
94 ResourceHandleClient* ResourceHandle::client() const
95 {
96     return d->m_client;
97 }
98
99 void ResourceHandle::setClient(ResourceHandleClient* client)
100 {
101     d->m_client = client;
102 }
103
104 const ResourceRequest& ResourceHandle::request() const
105 {
106     return d->m_request;
107 }
108
109 void ResourceHandle::clearAuthentication()
110 {
111 #if PLATFORM(MAC)
112     d->m_currentMacChallenge = nil;
113 #endif
114     d->m_currentWebChallenge.nullify();
115 }
116
117 static bool portAllowed(const ResourceRequest& request)
118 {
119     unsigned short port = request.url().port();
120
121     // Since most URLs don't have a port, return early for the "no port" case.
122     if (!port)
123         return true;
124
125     // This blocked port list matches the port blocking that Mozilla implements.
126     // See http://www.mozilla.org/projects/netlib/PortBanning.html for more information.
127     static const unsigned short blockedPortList[] = {
128         1,    // tcpmux
129         7,    // echo
130         9,    // discard
131         11,   // systat
132         13,   // daytime
133         15,   // netstat
134         17,   // qotd
135         19,   // chargen
136         20,   // FTP-data
137         21,   // FTP-control
138         22,   // SSH
139         23,   // telnet
140         25,   // SMTP
141         37,   // time
142         42,   // name
143         43,   // nicname
144         53,   // domain
145         77,   // priv-rjs
146         79,   // finger
147         87,   // ttylink
148         95,   // supdup
149         101,  // hostriame
150         102,  // iso-tsap
151         103,  // gppitnp
152         104,  // acr-nema
153         109,  // POP2
154         110,  // POP3
155         111,  // sunrpc
156         113,  // auth
157         115,  // SFTP
158         117,  // uucp-path
159         119,  // nntp
160         123,  // NTP
161         135,  // loc-srv / epmap
162         139,  // netbios
163         143,  // IMAP2
164         179,  // BGP
165         389,  // LDAP
166         465,  // SMTP+SSL
167         512,  // print / exec
168         513,  // login
169         514,  // shell
170         515,  // printer
171         526,  // tempo
172         530,  // courier
173         531,  // Chat
174         532,  // netnews
175         540,  // UUCP
176         556,  // remotefs
177         563,  // NNTP+SSL
178         587,  // ESMTP
179         601,  // syslog-conn
180         636,  // LDAP+SSL
181         993,  // IMAP+SSL
182         995,  // POP3+SSL
183         2049, // NFS
184         3659, // apple-sasl / PasswordServer [Apple addition]
185         4045, // lockd
186         6000, // X11
187     };
188     const unsigned short* const blockedPortListEnd = blockedPortList
189         + sizeof(blockedPortList) / sizeof(blockedPortList[0]);
190
191     // If the port is not in the blocked port list, allow it.
192     if (!std::binary_search(blockedPortList, blockedPortListEnd, port))
193         return true;
194
195     // Allow ports 21 and 22 for FTP URLs, as Mozilla does.
196     if ((port == 21 || port == 22) && request.url().protocolIs("ftp"))
197         return true;
198
199     // Allow any port number in a file URL, since the port number is ignored.
200     if (request.url().protocolIs("file"))
201         return true;
202
203     return false;
204 }
205   
206 bool ResourceHandle::shouldContentSniff() const
207 {
208     return d->m_shouldContentSniff;
209 }
210
211 bool ResourceHandle::shouldContentSniffURL(const KURL& url)
212 {
213 #if PLATFORM(MAC)
214     if (shouldForceContentSniffing)
215         return true;
216 #endif
217     // We shouldn't content sniff file URLs as their MIME type should be established via their extension.
218     return !url.protocolIs("file");
219 }
220
221 void ResourceHandle::forceContentSniffing()
222 {
223     shouldForceContentSniffing = true;
224 }
225
226 } // namespace WebCore