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