/src/PluginInstanceOpenWithFinder.mm
Objective C++ | 177 lines | 97 code | 31 blank | 49 comment | 13 complexity | 0c046ea5392116cd2a084ea2e7f2cc53 MD5 | raw file
1/* 2 * Copyright (C) 2005, 2006, 2007 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/* 30 * Modified by Sam Gross <colesbury@gmail.com> for use with Firefox PDF Plugin for Mac OS X. 31 */ 32#import "PluginInstance.h" 33#import <unistd.h> 34 35// This includes source code from the WebPDFView.mm in the WebKit project 36 37static inline id WebCFAutorelease(CFTypeRef obj) 38{ 39 if (obj) 40 CFMakeCollectable(obj); 41 [(id)obj autorelease]; 42 return (id)obj; 43} 44 45 46@interface PluginInstance (FileInternal) 47- (NSString *)_path; 48- (NSString *)_temporaryPDFDirectoryPath; 49@end 50 51@implementation PluginInstance (OpenWithFinder) 52 53- (NSData *)convertPostScriptDataSourceToPDF:(NSData *)data 54{ 55 // Convert PostScript to PDF using Quartz 2D API 56 // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_ps_convert/chapter_16_section_1.html 57 58 CGPSConverterCallbacks callbacks = { 0, 0, 0, 0, 0, 0, 0, 0 }; 59 CGPSConverterRef converter = CGPSConverterCreate(0, &callbacks, 0); 60 61 CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data); 62 63 CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); 64 65 CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(result); 66 67 // Error handled by detecting zero-length 'result' in caller 68 CGPSConverterConvert(converter, provider, consumer, 0); 69 70 CFRelease(converter); 71 CFRelease(provider); 72 CFRelease(consumer); 73 74 return WebCFAutorelease(result); 75} 76 77- (void)openWithFinder 78{ 79 // We don't want to write the file until we have a document to write. 80 if (!_data) { 81 NSBeep(); 82 return; 83 } 84 NSString *opath = [self _path]; 85 if (opath) { 86 if (!written) { 87 // Create a PDF file with the minimal permissions (only accessible to the current user, see 4145714) 88 NSNumber *permissions = [[NSNumber alloc] initWithInt:S_IRUSR]; 89 NSDictionary *fileAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:permissions, NSFilePosixPermissions, nil]; 90 [permissions release]; 91 92 [[NSFileManager defaultManager] createFileAtPath:opath 93 contents:_data 94 attributes:fileAttributes]; 95 [fileAttributes release]; 96 written = YES; 97 } 98 99 if (![[NSWorkspace sharedWorkspace] openFile:opath]) { 100 // NSWorkspace couldn't open file. Do we need an alert 101 // here? We ignore the error elsewhere. 102 } 103 } 104} 105 106- (NSString *)_path 107{ 108 // Generate path once. 109 if (path) 110 return path; 111 112 NSURLResponse *urlResponse = [[NSURLResponse alloc] 113 initWithURL:[NSURL URLWithString:_url] 114 MIMEType:_mimeType 115 expectedContentLength:-1 116 textEncodingName:nil]; 117 NSString *filename = [urlResponse suggestedFilename]; 118 [urlResponse autorelease]; 119 120 NSFileManager *manager = [NSFileManager defaultManager]; 121 NSString *temporaryPDFDirectoryPath = [self _temporaryPDFDirectoryPath]; 122 123 if (!temporaryPDFDirectoryPath) { 124 // This should never happen; if it does we'll fail silently on non-debug builds. 125 // ASSERT_NOT_REACHED(); 126 return nil; 127 } 128 129 path = [temporaryPDFDirectoryPath stringByAppendingPathComponent:filename]; 130 if ([manager fileExistsAtPath:path]) { 131 NSString *pathTemplatePrefix = [temporaryPDFDirectoryPath stringByAppendingPathComponent:@"XXXXXX-"]; 132 NSString *pathTemplate = [pathTemplatePrefix stringByAppendingString:filename]; 133 // fileSystemRepresentation returns a const char *; copy it into a char * so we can modify it safely 134 char *cPath = strdup([pathTemplate fileSystemRepresentation]); 135 int fd = mkstemps(cPath, strlen(cPath) - strlen([pathTemplatePrefix fileSystemRepresentation]) + 1); 136 if (fd < 0) { 137 // Couldn't create a temporary file! Should never happen; if it does we'll fail silently on non-debug builds. 138 // ASSERT_NOT_REACHED(); 139 path = nil; 140 } else { 141 close(fd); 142 path = [manager stringWithFileSystemRepresentation:cPath length:strlen(cPath)]; 143 } 144 free(cPath); 145 } 146 147 [path retain]; 148 149 return path; 150} 151 152- (NSString *)_temporaryPDFDirectoryPath 153{ 154 // Returns nil if the temporary PDF directory didn't exist and couldn't be created 155 156 static NSString *_temporaryPDFDirectoryPath = nil; 157 158 if (!_temporaryPDFDirectoryPath) { 159 NSString *temporaryDirectoryTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"FirefoxMacPDFs-XXXXXX"]; 160 char *cTemplate = strdup([temporaryDirectoryTemplate fileSystemRepresentation]); 161 162 if (!mkdtemp(cTemplate)) { 163 // This should never happen; if it does we'll fail silently on non-debug builds. 164 // ASSERT_NOT_REACHED(); 165 } else { 166 // cTemplate has now been modified to be the just-created directory name. This directory has 700 permissions, 167 // so only the current user can add to it or view its contents. 168 _temporaryPDFDirectoryPath = [[[NSFileManager defaultManager] stringWithFileSystemRepresentation:cTemplate length:strlen(cTemplate)] retain]; 169 } 170 171 free(cTemplate); 172 } 173 174 return _temporaryPDFDirectoryPath; 175} 176 177@end