2011-03-16 Pratik Solanki <psolanki@apple.com>
[WebKit-https.git] / Source / WebCore / platform / network / mac / WebCoreURLResponse.mm
1 /*
2  * Copyright (C) 2008, 2009 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "config.h"
30 #import "WebCoreURLResponse.h"
31
32 #import "MIMETypeRegistry.h"
33 #import "WebCoreSystemInterface.h"
34 #import <wtf/Assertions.h>
35 #import <wtf/RetainPtr.h>
36
37 namespace WebCore {
38
39 // <rdar://problem/5321972> Plain text document from HTTP server detected as application/octet-stream
40 // When we sniff a resource as application/octet-stream but the http response headers had "text/plain",
41 // we have a hard decision to make about which of the two generic MIME types to go with.
42 // When the URL's extension is a known binary type, we'll go with application/octet-stream.
43 // Otherwise, we'll trust the server.
44 static CFSetRef createBinaryExtensionsSet()
45 {
46     CFStringRef extensions[] = {
47         CFSTR("3g2"),
48         CFSTR("3gp"),
49         CFSTR("ai"),
50         CFSTR("aif"),
51         CFSTR("aifc"),
52         CFSTR("aiff"),
53         CFSTR("au"),
54         CFSTR("avi"),
55         CFSTR("bcpio"),
56         CFSTR("bin"),
57         CFSTR("bmp"),
58         CFSTR("boz"),
59         CFSTR("bpk"),
60         CFSTR("bz"),
61         CFSTR("bz2"),
62         CFSTR("chm"),
63         CFSTR("class"),
64         CFSTR("com"),
65         CFSTR("cpio"),
66         CFSTR("dcr"),
67         CFSTR("dir"),
68         CFSTR("dist"),
69         CFSTR("distz"),
70         CFSTR("dll"),
71         CFSTR("dmg"),
72         CFSTR("dms"),
73         CFSTR("doc"),
74         CFSTR("dot"),
75         CFSTR("dump"),
76         CFSTR("dv"),
77         CFSTR("dvi"),
78         CFSTR("dxr"),
79         CFSTR("elc"),
80         CFSTR("eot"),
81         CFSTR("eps"),
82         CFSTR("exe"),
83         CFSTR("fgd"),
84         CFSTR("gif"),
85         CFSTR("gtar"),
86         CFSTR("h261"),
87         CFSTR("h263"),
88         CFSTR("h264"),
89         CFSTR("ico"),
90         CFSTR("ims"),
91         CFSTR("indd"),
92         CFSTR("iso"),
93         CFSTR("jp2"),
94         CFSTR("jpe"),
95         CFSTR("jpeg"),
96         CFSTR("jpg"),
97         CFSTR("jpgm"),
98         CFSTR("jpgv"),
99         CFSTR("jpm"),
100         CFSTR("kar"),
101         CFSTR("kmz"),
102         CFSTR("lha"),
103         CFSTR("lrm"),
104         CFSTR("lzh"),
105         CFSTR("m1v"),
106         CFSTR("m2a"),
107         CFSTR("m2v"),
108         CFSTR("m3a"),
109         CFSTR("m3u"),
110         CFSTR("m4a"),
111         CFSTR("m4p"),
112         CFSTR("m4v"),
113         CFSTR("mdb"),
114         CFSTR("mid"),
115         CFSTR("midi"),
116         CFSTR("mj2"),
117         CFSTR("mjp2"),
118         CFSTR("mov"),
119         CFSTR("movie"),
120         CFSTR("mp2"),
121         CFSTR("mp2a"),
122         CFSTR("mp3"),
123         CFSTR("mp4"),
124         CFSTR("mp4a"),
125         CFSTR("mp4s"),
126         CFSTR("mp4v"),
127         CFSTR("mpe"),
128         CFSTR("mpeg"),
129         CFSTR("mpg"),
130         CFSTR("mpg4"),
131         CFSTR("mpga"),
132         CFSTR("mpp"),
133         CFSTR("mpt"),
134         CFSTR("msi"),
135         CFSTR("ogg"),
136         CFSTR("otf"),
137         CFSTR("pct"),
138         CFSTR("pdf"),
139         CFSTR("pfa"),
140         CFSTR("pfb"),
141         CFSTR("pic"),
142         CFSTR("pict"),
143         CFSTR("pkg"),
144         CFSTR("png"),
145         CFSTR("pot"),
146         CFSTR("pps"),
147         CFSTR("ppt"),
148         CFSTR("ps"),
149         CFSTR("psd"),
150         CFSTR("qt"),
151         CFSTR("qti"),
152         CFSTR("qtif"),
153         CFSTR("qwd"),
154         CFSTR("qwt"),
155         CFSTR("qxb"),
156         CFSTR("qxd"),
157         CFSTR("qxl"),
158         CFSTR("qxp"),
159         CFSTR("qxt"),
160         CFSTR("ra"),
161         CFSTR("ram"),
162         CFSTR("rm"),
163         CFSTR("rmi"),
164         CFSTR("rmp"),
165         CFSTR("scpt"),
166         CFSTR("sit"),
167         CFSTR("sitx"),
168         CFSTR("snd"),
169         CFSTR("so"),
170         CFSTR("swf"),
171         CFSTR("tar"),
172         CFSTR("tif"),
173         CFSTR("tiff"),
174         CFSTR("ttf"),
175         CFSTR("wav"),
176         CFSTR("wcm"),
177         CFSTR("wdb"),
178         CFSTR("wks"),
179         CFSTR("wm"),
180         CFSTR("wma"),
181         CFSTR("wmd"),
182         CFSTR("wmf"),
183         CFSTR("wmv"),
184         CFSTR("wmx"),
185         CFSTR("wmz"),
186         CFSTR("wpd"),
187         CFSTR("wpl"),
188         CFSTR("wps"),
189         CFSTR("wvx"),
190         CFSTR("xla"),
191         CFSTR("xlc"),
192         CFSTR("xlm"),
193         CFSTR("xls"),
194         CFSTR("xlt"),
195         CFSTR("xlw"),
196         CFSTR("xps"),
197         CFSTR("zip")
198     };
199     return CFSetCreate(kCFAllocatorDefault, (const void **)&extensions, sizeof(extensions)/sizeof(CFStringRef), &kCFTypeSetCallBacks);
200 }
201
202 // <rdar://problem/7007389> CoreTypes UTI map is missing 100+ file extensions that GateKeeper knew about
203 // When we disabled content sniffing for file URLs we caused problems with these 100+ extensions that CoreTypes
204 // doesn't know about.
205 // If CoreTypes is ever brought up to speed we can remove this table and associated code.
206 static CFDictionaryRef createExtensionToMIMETypeMap()
207 {
208     CFStringRef keys[] = {
209         CFSTR("ai"),
210         CFSTR("asc"),
211         CFSTR("bcpio"),
212         CFSTR("bmp"),
213         CFSTR("cdf"),
214         CFSTR("class"),
215         CFSTR("cpgz"),
216         CFSTR("cpio"),
217         CFSTR("cpt"),
218         CFSTR("csh"),
219         CFSTR("css"),
220         CFSTR("dcr"),
221         CFSTR("dir"),
222         CFSTR("dmg"),
223         CFSTR("dms"),
224         CFSTR("dvi"),
225         CFSTR("dxr"),
226         CFSTR("eps"),
227         CFSTR("etx"),
228         CFSTR("ez"),
229         CFSTR("fdf"),
230         CFSTR("fla"),
231         CFSTR("fp"),
232         CFSTR("fp2"),
233         CFSTR("fp3"),
234         CFSTR("fp4"),
235         CFSTR("fp5"),
236         CFSTR("fp6"),
237         CFSTR("hdf"),
238         CFSTR("ice"),
239         CFSTR("ico"),
240         CFSTR("ics"),
241         CFSTR("ief"),
242         CFSTR("iges"),
243         CFSTR("igs"),
244         CFSTR("iso"),
245         CFSTR("jhtml"),
246         CFSTR("latex"),
247         CFSTR("lha"),
248         CFSTR("lzh"),
249         CFSTR("m3u"),
250         CFSTR("m4p"),
251         CFSTR("mac"),
252         CFSTR("man"),
253         CFSTR("me"),
254         CFSTR("mesh"),
255         CFSTR("mif"),
256         CFSTR("movie"),
257         CFSTR("mp2"),
258         CFSTR("mpga"),
259         CFSTR("ms"),
260         CFSTR("msh"),
261         CFSTR("mxu"),
262         CFSTR("nc"),
263         CFSTR("oda"),
264         CFSTR("pbm"),
265         CFSTR("pcx"),
266         CFSTR("pdb"),
267         CFSTR("pgm"),
268         CFSTR("pgn"),
269         CFSTR("pls"),
270         CFSTR("pnm"),
271         CFSTR("pnt"),
272         CFSTR("pntg"),
273         CFSTR("ppm"),
274         CFSTR("ras"),
275         CFSTR("rgb"),
276         CFSTR("roff"),
277         CFSTR("rpm"),
278         CFSTR("rtx"),
279         CFSTR("sgm"),
280         CFSTR("sgml"),
281         CFSTR("sh"),
282         CFSTR("shar"),
283         CFSTR("silo"),
284         CFSTR("skd"),
285         CFSTR("skm"),
286         CFSTR("skp"),
287         CFSTR("skt"),
288         CFSTR("smi"),
289         CFSTR("so"),
290         CFSTR("spl"),
291         CFSTR("src"),
292         CFSTR("sv4cpio"),
293         CFSTR("sv4crc"),
294         CFSTR("swf"),
295         CFSTR("t"),
296         CFSTR("targa"),
297         CFSTR("tcl"),
298         CFSTR("tex"),
299         CFSTR("texi"),
300         CFSTR("texinfo"),
301         CFSTR("tgz"),
302         CFSTR("torrent"),
303         CFSTR("tr"),
304         CFSTR("tsv"),
305         CFSTR("ustar"),
306         CFSTR("vcd"),
307         CFSTR("vrml"),
308         CFSTR("wbmp"),
309         CFSTR("wbxml"),
310         CFSTR("webarchive"),
311         CFSTR("wmd"),
312         CFSTR("wml"),
313         CFSTR("wmlc"),
314         CFSTR("wmls"),
315         CFSTR("wmlsc"),
316         CFSTR("wrl"),
317         CFSTR("xdp"),
318         CFSTR("xfd"),
319         CFSTR("xfdf"),
320         CFSTR("xpm"),
321         CFSTR("xsl"),
322         CFSTR("xwd"),
323         CFSTR("xyz"),
324         CFSTR("z")
325     };
326
327     CFStringRef values[] = {
328         CFSTR("application/postscript"),
329         CFSTR("text/plain"),
330         CFSTR("application/x-bcpio"),
331         CFSTR("image/bmp"),
332         CFSTR("application/x-netcdf"),
333         CFSTR("application/octet-stream"),
334         CFSTR("application/x-gzip"),
335         CFSTR("application/x-cpio"),
336         CFSTR("application/mac-compactpro"),
337         CFSTR("application/x-csh"),
338         CFSTR("text/css"),
339         CFSTR("application/x-director"),
340         CFSTR("application/x-director"),
341         CFSTR("application/x-diskcopy"),
342         CFSTR("application/octet-stream"),
343         CFSTR("application/x-dvi"),
344         CFSTR("application/x-director"),
345         CFSTR("application/postscript"),
346         CFSTR("text/x-setext"),
347         CFSTR("application/andrew-inset"),
348         CFSTR("application/vnd.fdf"),
349         CFSTR("application/octet-stream"),
350         CFSTR("application/x-filemaker"),
351         CFSTR("application/x-filemaker"),
352         CFSTR("application/x-filemaker"),
353         CFSTR("application/x-filemaker"),
354         CFSTR("application/x-filemaker"),
355         CFSTR("application/x-filemaker"),
356         CFSTR("application/x-hdf"),
357         CFSTR("x-conference/x-cooltalk"),
358         CFSTR("image/x-icon"),
359         CFSTR("text/calendar"),
360         CFSTR("image/ief"),
361         CFSTR("model/iges"),
362         CFSTR("model/iges"),
363         CFSTR("application/octet-stream"),
364         CFSTR("text/html"),
365         CFSTR("application/x-latex"),
366         CFSTR("application/octet-stream"),
367         CFSTR("application/octet-stream"),
368         CFSTR("audio/x-mpegurl"),
369         CFSTR("audio/x-m4p"),
370         CFSTR("image/x-macpaint"),
371         CFSTR("application/x-troff-man"),
372         CFSTR("application/x-troff-me"),
373         CFSTR("model/mesh"),
374         CFSTR("application/vnd.mif"),
375         CFSTR("video/x-sgi-movie"),
376         CFSTR("audio/mpeg"),
377         CFSTR("audio/mpeg"),
378         CFSTR("application/x-troff-ms"),
379         CFSTR("model/mesh"),
380         CFSTR("video/vnd.mpegurl"),
381         CFSTR("application/x-netcdf"),
382         CFSTR("application/oda"),
383         CFSTR("image/x-portable-bitmap"),
384         CFSTR("image/x-pcx"),
385         CFSTR("chemical/x-pdb"),
386         CFSTR("image/x-portable-graymap"),
387         CFSTR("application/x-chess-pgn"),
388         CFSTR("audio/scpls"),
389         CFSTR("image/x-portable-anymap"),
390         CFSTR("image/x-macpaint"),
391         CFSTR("image/x-macpaint"),
392         CFSTR("image/x-portable-pixmap"),
393         CFSTR("image/x-cmu-raster"),
394         CFSTR("image/x-rgb"),
395         CFSTR("application/x-troff"),
396         CFSTR("audio/x-pn-realaudio-plugin"),
397         CFSTR("text/richtext"),
398         CFSTR("text/sgml"),
399         CFSTR("text/sgml"),
400         CFSTR("application/x-sh"),
401         CFSTR("application/x-shar"),
402         CFSTR("model/mesh"),
403         CFSTR("application/x-koan"),
404         CFSTR("application/x-koan"),
405         CFSTR("application/x-koan"),
406         CFSTR("application/x-koan"),
407         CFSTR("application/x-diskcopy"),
408         CFSTR("application/octet-stream"),
409         CFSTR("application/x-futuresplash"),
410         CFSTR("application/x-wais-source"),
411         CFSTR("application/x-sv4cpio"),
412         CFSTR("application/x-sv4crc"),
413         CFSTR("application/x-shockwave-flash"),
414         CFSTR("application/x-troff"),
415         CFSTR("image/x-targa"),
416         CFSTR("application/x-tcl"),
417         CFSTR("application/x-tex"),
418         CFSTR("application/x-texinfo"),
419         CFSTR("application/x-texinfo"),
420         CFSTR("application/x-gzip"),
421         CFSTR("application/x-bittorrent"),
422         CFSTR("application/x-troff"),
423         CFSTR("text/tab-separated-values"),
424         CFSTR("application/x-ustar"),
425         CFSTR("application/x-cdlink"),
426         CFSTR("model/vrml"),
427         CFSTR("image/vnd.wap.wbmp"),
428         CFSTR("application/vnd.wap.wbxml"),
429         CFSTR("application/x-webarchive"),
430         CFSTR("application/x-ms-wmd"),
431         CFSTR("text/vnd.wap.wml"),
432         CFSTR("application/vnd.wap.wmlc"),
433         CFSTR("text/vnd.wap.wmlscript"),
434         CFSTR("application/vnd.wap.wmlscriptc"),
435         CFSTR("model/vrml"),
436         CFSTR("application/vnd.adobe.xdp+xml"),
437         CFSTR("application/vnd.adobe.xfd+xml"),
438         CFSTR("application/vnd.adobe.xfdf"),
439         CFSTR("image/x-xpixmap"),
440         CFSTR("text/xml"),
441         CFSTR("image/x-xwindowdump"),
442         CFSTR("chemical/x-xyz"),
443         CFSTR("application/x-compress")
444     };
445
446     ASSERT(sizeof(keys) == sizeof(values));
447     return CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys, (const void**)&values, sizeof(keys)/sizeof(CFStringRef), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
448 }
449
450 static RetainPtr<CFStringRef> mimeTypeFromUTITree(CFStringRef uti)
451 {
452     // Check if this UTI has a MIME type.
453     RetainPtr<CFStringRef> mimeType(AdoptCF, UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
454     if (mimeType)
455         return mimeType.get();
456     
457     // If not, walk the ancestory of this UTI via its "ConformsTo" tags and return the first MIME type we find.
458     RetainPtr<CFDictionaryRef> decl(AdoptCF, UTTypeCopyDeclaration(uti));
459     if (!decl)
460         return nil;
461     CFTypeRef value = CFDictionaryGetValue(decl.get(), kUTTypeConformsToKey);
462     if (!value)
463         return nil;
464     CFTypeID typeID = CFGetTypeID(value);
465     
466     if (typeID == CFStringGetTypeID())
467         return mimeTypeFromUTITree((CFStringRef)value);
468
469     if (typeID == CFArrayGetTypeID()) {
470         CFArrayRef newTypes = (CFArrayRef)value;
471         CFIndex count = CFArrayGetCount(newTypes);
472         for (CFIndex i = 0; i < count; ++i) {
473             CFTypeRef object = CFArrayGetValueAtIndex(newTypes, i);
474             if (CFGetTypeID(object) != CFStringGetTypeID())
475                 continue;
476
477             if (RetainPtr<CFStringRef> mimeType = mimeTypeFromUTITree((CFStringRef)object))
478                 return mimeType;
479         }
480     }
481     
482     return nil;
483 }
484
485 void adjustMIMETypeIfNecessary(CFURLResponseRef cfResponse)
486 {
487     RetainPtr<CFStringRef> result = wkGetCFURLResponseMIMEType(cfResponse);
488     RetainPtr<CFStringRef> originalResult = result;
489
490     if (!result) {
491         CFURLRef url = wkGetCFURLResponseURL(cfResponse);
492         NSURL *nsURL = (NSURL *)url;
493         if ([nsURL isFileURL]) {
494             RetainPtr<CFStringRef> extension(AdoptCF, CFURLCopyPathExtension(url));
495             if (extension) {
496                 // <rdar://problem/7007389> CoreTypes UTI map is missing 100+ file extensions that GateKeeper knew about
497                 // When this radar is resolved, we can remove this file:// url specific code.
498                 static CFDictionaryRef extensionMap = createExtensionToMIMETypeMap();
499                 CFMutableStringRef mutableExtension = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, extension.get());
500                 CFStringLowercase(mutableExtension, NULL);
501                 extension.adoptCF(mutableExtension);
502                 result = (CFStringRef) CFDictionaryGetValue(extensionMap, extension.get());
503                 
504                 if (!result) {
505                     // If the Gatekeeper-based map doesn't have a MIME type, we'll try to figure out what it should be by
506                     // looking up the file extension in the UTI maps.
507                     RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension.get(), 0));
508                     result = mimeTypeFromUTITree(uti.get());
509                 }
510             }
511         }
512     }
513     
514     if (!result) {
515         static CFStringRef defaultMIMETypeString = WebCore::defaultMIMEType().createCFString();
516         result = defaultMIMETypeString;
517     }
518
519     // <rdar://problem/5321972> Plain text document from HTTP server detected as application/octet-stream
520     // Make the best guess when deciding between "generic binary" and "generic text" using a table of known binary MIME types.
521     if (CFStringCompare(result.get(), CFSTR("application/octet-stream"), 0) == kCFCompareEqualTo) {
522         CFHTTPMessageRef message = wkGetCFURLResponseHTTPResponse(cfResponse);
523         if (message) {
524             RetainPtr<CFStringRef> contentType(AdoptCF, CFHTTPMessageCopyHeaderFieldValue(message, CFSTR("Content-Type")));
525             if (contentType && CFStringHasPrefix(contentType.get(), CFSTR("text/plain"))) {
526                 static CFSetRef binaryExtensions = createBinaryExtensionsSet();
527                 RetainPtr<NSString> suggestedFilename(AdoptNS, (NSString *)wkCopyCFURLResponseSuggestedFilename(cfResponse));
528                 if (!CFSetContainsValue(binaryExtensions, (CFStringRef) [[suggestedFilename.get() pathExtension] lowercaseString]))
529                     result = CFSTR("text/plain");
530             }
531         }
532     }
533
534 #ifdef BUILDING_ON_LEOPARD
535     // Workaround for <rdar://problem/5539824>
536     if (CFStringCompare(result.get(), CFSTR("text/xml"), 0) == kCFCompareEqualTo)
537         result = CFSTR("application/xml");
538 #endif
539
540     if (result != originalResult)
541         wkSetCFURLResponseMIMEType(cfResponse, result.get());
542 }
543
544 }