diff -r 000000000000 -r 4f2f89ce4247 WebKit/mac/WebView/WebPDFDocumentExtras.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebKit/mac/WebView/WebPDFDocumentExtras.mm Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebPDFDocumentExtras.h" + +#import "WebTypesInternal.h" +#import +#import +#import +#import + +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) +@interface PDFDocument (Internal) +- (CGPDFDocumentRef)documentRef; +@end +#endif + +static void appendValuesInPDFNameSubtreeToVector(CGPDFDictionaryRef subtree, Vector& values) +{ + CGPDFArrayRef names; + if (CGPDFDictionaryGetArray(subtree, "Names", &names)) { + size_t nameCount = CGPDFArrayGetCount(names) / 2; + for (size_t i = 0; i < nameCount; ++i) { + CGPDFObjectRef object; + CGPDFArrayGetObject(names, 2 * i + 1, &object); + values.append(object); + } + return; + } + + CGPDFArrayRef kids; + if (!CGPDFDictionaryGetArray(subtree, "Kids", &kids)) + return; + + size_t kidCount = CGPDFArrayGetCount(kids); + for (size_t i = 0; i < kidCount; ++i) { + CGPDFDictionaryRef kid; + if (!CGPDFArrayGetDictionary(kids, i, &kid)) + continue; + appendValuesInPDFNameSubtreeToVector(kid, values); + } +} + +static void getAllValuesInPDFNameTree(CGPDFDictionaryRef tree, Vector& allValues) +{ + appendValuesInPDFNameSubtreeToVector(tree, allValues); +} + +NSArray *allScriptsInPDFDocument(PDFDocument *document) +{ + NSMutableArray *scripts = [NSMutableArray array]; + CGPDFDocumentRef pdfDocument = [document documentRef]; + if (!pdfDocument) + return scripts; + + CGPDFDictionaryRef pdfCatalog = CGPDFDocumentGetCatalog(pdfDocument); + if (!pdfCatalog) + return scripts; + + // Get the dictionary of all document-level name trees. + CGPDFDictionaryRef namesDictionary; + if (!CGPDFDictionaryGetDictionary(pdfCatalog, "Names", &namesDictionary)) + return scripts; + + // Get the document-level "JavaScript" name tree. + CGPDFDictionaryRef javaScriptNameTree; + if (!CGPDFDictionaryGetDictionary(namesDictionary, "JavaScript", &javaScriptNameTree)) + return scripts; + + // The names are aribtrary. We are only interested in the values. + Vector objects; + getAllValuesInPDFNameTree(javaScriptNameTree, objects); + size_t objectCount = objects.size(); + + for (size_t i = 0; i < objectCount; ++i) { + CGPDFDictionaryRef javaScriptAction; + if (!CGPDFObjectGetValue(reinterpret_cast(objects[i]), kCGPDFObjectTypeDictionary, &javaScriptAction)) + continue; + + // A JavaScript action must have an action type of "JavaScript". + const char* actionType; + if (!CGPDFDictionaryGetName(javaScriptAction, "S", &actionType) || strcmp(actionType, "JavaScript")) + continue; + + const UInt8* bytes = 0; + CFIndex length; + CGPDFStreamRef stream; + CGPDFStringRef string; + RetainPtr data; + if (CGPDFDictionaryGetStream(javaScriptAction, "JS", &stream)) { + CGPDFDataFormat format; + data.adoptCF(CGPDFStreamCopyData(stream, &format)); + if (!data) + continue; + bytes = CFDataGetBytePtr(data.get()); + length = CFDataGetLength(data.get()); + } else if (CGPDFDictionaryGetString(javaScriptAction, "JS", &string)) { + bytes = CGPDFStringGetBytePtr(string); + length = CGPDFStringGetLength(string); + } + if (!bytes) + continue; + + NSStringEncoding encoding = (length > 1 && bytes[0] == 0xFE && bytes[1] == 0xFF) ? NSUnicodeStringEncoding : NSUTF8StringEncoding; + NSString *script = [[NSString alloc] initWithBytes:bytes length:length encoding:encoding]; + [scripts addObject:script]; + [script release]; + } + + return scripts; +}