Detect scripted auto-print requests
Fixes #6106 To avoid future regressions, two new unit tests were added: 1. A new PDF based on the report from #6106, which contains an OpenAction of type JavaScript and a string "this.print({...}". 2. An existing PDF from https://bugzil.la/1001080 (from #4698). Although it does not matter, since we don't execute the JavaScript code, I have also changed "print(true)" to "print({})" since the print method takes an object (not a boolean). See "Printing PDF documents", page 62: http://adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/js_developer_guide.pdf
This commit is contained in:
parent
d3e90cf825
commit
c676ecb5a0
@ -534,6 +534,19 @@ var Catalog = (function CatalogClosure() {
|
|||||||
var obj = this.catDict.get('Names');
|
var obj = this.catDict.get('Names');
|
||||||
|
|
||||||
var javaScript = [];
|
var javaScript = [];
|
||||||
|
function appendIfJavaScriptDict(jsDict) {
|
||||||
|
var type = jsDict.get('S');
|
||||||
|
if (!isName(type) || type.name !== 'JavaScript') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var js = jsDict.get('JS');
|
||||||
|
if (isStream(js)) {
|
||||||
|
js = bytesToString(js.getBytes());
|
||||||
|
} else if (!isString(js)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
javaScript.push(stringToPDFString(js));
|
||||||
|
}
|
||||||
if (obj && obj.has('JavaScript')) {
|
if (obj && obj.has('JavaScript')) {
|
||||||
var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
|
var nameTree = new NameTree(obj.getRaw('JavaScript'), xref);
|
||||||
var names = nameTree.getAll();
|
var names = nameTree.getAll();
|
||||||
@ -544,36 +557,25 @@ var Catalog = (function CatalogClosure() {
|
|||||||
// We don't really use the JavaScript right now. This code is
|
// We don't really use the JavaScript right now. This code is
|
||||||
// defensive so we don't cause errors on document load.
|
// defensive so we don't cause errors on document load.
|
||||||
var jsDict = names[name];
|
var jsDict = names[name];
|
||||||
if (!isDict(jsDict)) {
|
if (isDict(jsDict)) {
|
||||||
continue;
|
appendIfJavaScriptDict(jsDict);
|
||||||
}
|
}
|
||||||
var type = jsDict.get('S');
|
|
||||||
if (!isName(type) || type.name !== 'JavaScript') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var js = jsDict.get('JS');
|
|
||||||
if (!isString(js) && !isStream(js)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isStream(js)) {
|
|
||||||
js = bytesToString(js.getBytes());
|
|
||||||
}
|
|
||||||
javaScript.push(stringToPDFString(js));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append OpenAction actions to javaScript array
|
// Append OpenAction actions to javaScript array
|
||||||
var openactionDict = this.catDict.get('OpenAction');
|
var openactionDict = this.catDict.get('OpenAction');
|
||||||
if (isDict(openactionDict)) {
|
if (isDict(openactionDict, 'Action')) {
|
||||||
var objType = openactionDict.get('Type');
|
|
||||||
var actionType = openactionDict.get('S');
|
var actionType = openactionDict.get('S');
|
||||||
var action = openactionDict.get('N');
|
if (isName(actionType) && actionType.name === 'Named') {
|
||||||
var isPrintAction = (isName(objType) && objType.name === 'Action' &&
|
// The named Print action is not a part of the PDF 1.7 specification,
|
||||||
isName(actionType) && actionType.name === 'Named' &&
|
// but is supported by many PDF readers/writers (including Adobe's).
|
||||||
isName(action) && action.name === 'Print');
|
var action = openactionDict.get('N');
|
||||||
|
if (isName(action) && action.name === 'Print') {
|
||||||
if (isPrintAction) {
|
javaScript.push('print({});');
|
||||||
javaScript.push('print(true);');
|
}
|
||||||
|
} else {
|
||||||
|
appendIfJavaScriptDict(openactionDict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
test/pdfs/.gitignore
vendored
2
test/pdfs/.gitignore
vendored
@ -146,4 +146,6 @@
|
|||||||
!issue6068.pdf
|
!issue6068.pdf
|
||||||
!issue6081.pdf
|
!issue6081.pdf
|
||||||
!issue6069.pdf
|
!issue6069.pdf
|
||||||
|
!issue6106.pdf
|
||||||
|
!bug1001080.pdf
|
||||||
!issue6108.pdf
|
!issue6108.pdf
|
||||||
|
BIN
test/pdfs/bug1001080.pdf
Normal file
BIN
test/pdfs/bug1001080.pdf
Normal file
Binary file not shown.
70
test/pdfs/issue6106.pdf
Normal file
70
test/pdfs/issue6106.pdf
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
%PDF-1.4
|
||||||
|
% To manually verify that PDF.js works as expected, open this PDF file with
|
||||||
|
% PDF.js and check whether the browser attempts to print the PDF.
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Catalog
|
||||||
|
/Pages 2 0 R
|
||||||
|
/OpenAction 3 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Pages
|
||||||
|
/Count 1
|
||||||
|
/Kids [4 0 R]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Action
|
||||||
|
/S /JavaScript
|
||||||
|
% This is a verbatim copy from a PDF generated by Google Drive (20 July 2015)
|
||||||
|
/JS (this.print\({bUI:true,bSilent:false,bShrinkToFit:true}\);)
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Parent 2 0 R
|
||||||
|
/Contents 6 0 R
|
||||||
|
/Type /Page
|
||||||
|
/Resources 5 0 R
|
||||||
|
/MediaBox [0 0 400 200]
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
<<
|
||||||
|
/Font
|
||||||
|
<<
|
||||||
|
/F1
|
||||||
|
<<
|
||||||
|
/Type /Font
|
||||||
|
/Subtype /Type1
|
||||||
|
/BaseFont /Arial
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<</Length 58>>
|
||||||
|
stream
|
||||||
|
BT/F1 20 Tf 70 88 Td(Should trigger a print action.) Tj ET
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 7
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000151 00000 n
|
||||||
|
0000000218 00000 n
|
||||||
|
0000000275 00000 n
|
||||||
|
0000000467 00000 n
|
||||||
|
0000000571 00000 n
|
||||||
|
0000000685 00000 n
|
||||||
|
trailer
|
||||||
|
<<
|
||||||
|
/Root 1 0 R
|
||||||
|
/Size 7
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
791
|
||||||
|
%%EOF
|
@ -147,6 +147,32 @@ describe('api', function() {
|
|||||||
expect(data).toEqual([]);
|
expect(data).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// Keep this in sync with the pattern in viewer.js. The pattern is used to
|
||||||
|
// detect whether or not to automatically start printing.
|
||||||
|
var viewerPrintRegExp = /\bprint\s*\(/;
|
||||||
|
it('gets javascript with printing instructions (Print action)', function() {
|
||||||
|
// PDF document with "Print" Named action in OpenAction
|
||||||
|
var pdfUrl = combineUrl(window.location.href, '../pdfs/bug1001080.pdf');
|
||||||
|
var promise = PDFJS.getDocument(pdfUrl).then(function(doc) {
|
||||||
|
return doc.getJavaScript();
|
||||||
|
});
|
||||||
|
waitsForPromiseResolved(promise, function (data) {
|
||||||
|
expect(data).toEqual(['print({});']);
|
||||||
|
expect(data[0]).toMatch(viewerPrintRegExp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('gets javascript with printing instructions (JS action)', function() {
|
||||||
|
// PDF document with "JavaScript" action in OpenAction
|
||||||
|
var pdfUrl = combineUrl(window.location.href, '../pdfs/issue6106.pdf');
|
||||||
|
var promise = PDFJS.getDocument(pdfUrl).then(function(doc) {
|
||||||
|
return doc.getJavaScript();
|
||||||
|
});
|
||||||
|
waitsForPromiseResolved(promise, function (data) {
|
||||||
|
expect(data).toEqual(
|
||||||
|
['this.print({bUI:true,bSilent:false,bShrinkToFit:true});']);
|
||||||
|
expect(data[0]).toMatch(viewerPrintRegExp);
|
||||||
|
});
|
||||||
|
});
|
||||||
it('gets outline', function() {
|
it('gets outline', function() {
|
||||||
var promise = doc.getOutline();
|
var promise = doc.getOutline();
|
||||||
waitsForPromiseResolved(promise, function(outline) {
|
waitsForPromiseResolved(promise, function(outline) {
|
||||||
|
@ -820,7 +820,7 @@ var PDFViewerApplication = {
|
|||||||
self.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript);
|
self.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript);
|
||||||
}
|
}
|
||||||
// Hack to support auto printing.
|
// Hack to support auto printing.
|
||||||
var regex = /\bprint\s*\(/g;
|
var regex = /\bprint\s*\(/;
|
||||||
for (var i = 0, ii = javaScript.length; i < ii; i++) {
|
for (var i = 0, ii = javaScript.length; i < ii; i++) {
|
||||||
var js = javaScript[i];
|
var js = javaScript[i];
|
||||||
if (js && regex.test(js)) {
|
if (js && regex.test(js)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user