PageRenderTime 60ms CodeModel.GetById 57ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/src/PluginInstanceOpenWithFinder.mm

http://firefox-mac-pdf.googlecode.com/
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