Strip null (\x00) characters from the URLs in LinkAnnotations (issue 6832)

Apparently some PDF files can have annotations with `URI` entries ending with `null` characters, thus breaking the links.
To handle this edge-case of bad PDFs, this patch moves the already existing utility function from `ui_utils.js` into `util.js`, in order to fix those URLs.

Fixes 6832.
This commit is contained in:
Jonas Jenwald 2016-01-04 21:33:41 +01:00
parent 4e9ea35eee
commit 97c10e9c08
7 changed files with 33 additions and 25 deletions

View File

@ -33,6 +33,7 @@ var AnnotationType = sharedUtil.AnnotationType;
var Util = sharedUtil.Util; var Util = sharedUtil.Util;
var isExternalLinkTargetSet = sharedUtil.isExternalLinkTargetSet; var isExternalLinkTargetSet = sharedUtil.isExternalLinkTargetSet;
var LinkTargetStringMap = sharedUtil.LinkTargetStringMap; var LinkTargetStringMap = sharedUtil.LinkTargetStringMap;
var removeNullCharacters = sharedUtil.removeNullCharacters;
var warn = sharedUtil.warn; var warn = sharedUtil.warn;
var CustomStyle = displayDOMUtils.CustomStyle; var CustomStyle = displayDOMUtils.CustomStyle;
@ -232,7 +233,8 @@ var LinkAnnotationElement = (function LinkAnnotationElementClosure() {
this.container.className = 'linkAnnotation'; this.container.className = 'linkAnnotation';
var link = document.createElement('a'); var link = document.createElement('a');
link.href = link.title = this.data.url || ''; link.href = link.title = (this.data.url ?
removeNullCharacters(this.data.url) : '');
if (this.data.url && isExternalLinkTargetSet()) { if (this.data.url && isExternalLinkTargetSet()) {
link.target = LinkTargetStringMap[PDFJS.externalLinkTarget]; link.target = LinkTargetStringMap[PDFJS.externalLinkTarget];

View File

@ -504,6 +504,16 @@ var XRefParseException = (function XRefParseExceptionClosure() {
return XRefParseException; return XRefParseException;
})(); })();
var NullCharactersRegExp = /\x00/g;
function removeNullCharacters(str) {
if (typeof str !== 'string') {
warn('The argument for removeNullCharacters must be a string.');
return str;
}
return str.replace(NullCharactersRegExp, '');
}
PDFJS.removeNullCharacters = removeNullCharacters;
function bytesToString(bytes) { function bytesToString(bytes) {
assert(bytes !== null && typeof bytes === 'object' && assert(bytes !== null && typeof bytes === 'object' &&
@ -1690,6 +1700,7 @@ exports.log2 = log2;
exports.readInt8 = readInt8; exports.readInt8 = readInt8;
exports.readUint16 = readUint16; exports.readUint16 = readUint16;
exports.readUint32 = readUint32; exports.readUint32 = readUint32;
exports.removeNullCharacters = removeNullCharacters;
exports.shadow = shadow; exports.shadow = shadow;
exports.string32 = string32; exports.string32 = string32;
exports.stringToBytes = stringToBytes; exports.stringToBytes = stringToBytes;

View File

@ -1,20 +1,8 @@
/* globals expect, it, describe, binarySearchFirstItem, removeNullCharacters */ /* globals expect, it, describe, binarySearchFirstItem */
'use strict'; 'use strict';
describe('ui_utils', function() { describe('ui_utils', function() {
describe('removeNullCharacters', function() {
it('should not modify string without null characters', function() {
var str = 'string without null chars';
expect(removeNullCharacters(str)).toEqual('string without null chars');
});
it('should modify string with null characters', function() {
var str = 'string\x00With\x00Null\x00Chars';
expect(removeNullCharacters(str)).toEqual('stringWithNullChars');
});
});
describe('binary search', function() { describe('binary search', function() {
function isTrue(boolean) { function isTrue(boolean) {
return boolean; return boolean;

View File

@ -1,5 +1,6 @@
/* globals expect, it, describe, combineUrl, Dict, isDict, Name, PDFJS, /* globals expect, it, describe, combineUrl, Dict, isDict, Name, PDFJS,
stringToPDFString, isExternalLinkTargetSet, LinkTarget */ stringToPDFString, isExternalLinkTargetSet, LinkTarget,
removeNullCharacters */
'use strict'; 'use strict';
@ -125,4 +126,16 @@ describe('util', function() {
// Reset the state. // Reset the state.
PDFJS.externalLinkTarget = previousExternalLinkTarget; PDFJS.externalLinkTarget = previousExternalLinkTarget;
}); });
describe('removeNullCharacters', function() {
it('should not modify string without null characters', function() {
var str = 'string without null chars';
expect(removeNullCharacters(str)).toEqual('string without null chars');
});
it('should modify string with null characters', function() {
var str = 'string\x00With\x00Null\x00Chars';
expect(removeNullCharacters(str)).toEqual('stringWithNullChars');
});
});
}); });

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals getFileName, removeNullCharacters */ /* globals getFileName, PDFJS */
'use strict'; 'use strict';
@ -89,7 +89,7 @@ var PDFAttachmentView = (function PDFAttachmentViewClosure() {
div.className = 'attachmentsItem'; div.className = 'attachmentsItem';
var button = document.createElement('button'); var button = document.createElement('button');
this._bindLink(button, item.content, filename); this._bindLink(button, item.content, filename);
button.textContent = removeNullCharacters(filename); button.textContent = PDFJS.removeNullCharacters(filename);
div.appendChild(button); div.appendChild(button);
this.container.appendChild(div); this.container.appendChild(div);
} }

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals removeNullCharacters */ /* globals PDFJS */
'use strict'; 'use strict';
@ -137,7 +137,7 @@ var PDFOutlineView = (function PDFOutlineViewClosure() {
div.className = 'outlineItem'; div.className = 'outlineItem';
var element = document.createElement('a'); var element = document.createElement('a');
this._bindLink(element, item); this._bindLink(element, item);
element.textContent = removeNullCharacters(item.title); element.textContent = PDFJS.removeNullCharacters(item.title);
div.appendChild(element); div.appendChild(element);
if (item.items.length > 0) { if (item.items.length > 0) {

View File

@ -23,12 +23,6 @@ var MAX_AUTO_SCALE = 1.25;
var SCROLLBAR_PADDING = 40; var SCROLLBAR_PADDING = 40;
var VERTICAL_PADDING = 5; var VERTICAL_PADDING = 5;
var NullCharactersRegExp = /\x00/g;
function removeNullCharacters(str) {
return str.replace(NullCharactersRegExp, '');
}
function getFileName(url) { function getFileName(url) {
var anchor = url.indexOf('#'); var anchor = url.indexOf('#');
var query = url.indexOf('?'); var query = url.indexOf('?');