2015-04-28 00:25:32 +09:00
|
|
|
/* Copyright 2015 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2016-04-09 02:34:27 +09:00
|
|
|
(function (root, factory) {
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
2016-04-26 07:57:15 +09:00
|
|
|
define('pdfjs-web/pdf_link_service', ['exports', 'pdfjs-web/ui_utils',
|
|
|
|
'pdfjs-web/dom_events'], factory);
|
2016-04-09 02:34:27 +09:00
|
|
|
} else if (typeof exports !== 'undefined') {
|
2016-04-26 07:57:15 +09:00
|
|
|
factory(exports, require('./ui_utils.js'), require('./dom_events.js'));
|
2016-04-09 02:34:27 +09:00
|
|
|
} else {
|
2016-04-26 07:57:15 +09:00
|
|
|
factory((root.pdfjsWebPDFLinkService = {}), root.pdfjsWebUIUtils,
|
|
|
|
root.pdfjsWebDOMEvents);
|
2016-04-09 02:34:27 +09:00
|
|
|
}
|
2016-04-26 07:57:15 +09:00
|
|
|
}(this, function (exports, uiUtils, domEvents) {
|
2016-04-09 02:34:27 +09:00
|
|
|
|
|
|
|
var parseQueryString = uiUtils.parseQueryString;
|
|
|
|
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
var PageNumberRegExp = /^\d+$/;
|
|
|
|
function isPageNumber(str) {
|
|
|
|
return PageNumberRegExp.test(str);
|
|
|
|
}
|
|
|
|
|
2016-04-26 07:57:15 +09:00
|
|
|
/**
|
|
|
|
* @typedef {Object} PDFLinkServiceOptions
|
|
|
|
* @property {EventBus} eventBus - The application event bus.
|
|
|
|
*/
|
|
|
|
|
2015-04-28 00:25:32 +09:00
|
|
|
/**
|
|
|
|
* Performs navigation functions inside PDF, such as opening specified page,
|
|
|
|
* or destination.
|
|
|
|
* @class
|
|
|
|
* @implements {IPDFLinkService}
|
|
|
|
*/
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
var PDFLinkService = (function PDFLinkServiceClosure() {
|
2015-04-28 00:25:32 +09:00
|
|
|
/**
|
|
|
|
* @constructs PDFLinkService
|
2016-04-26 07:57:15 +09:00
|
|
|
* @param {PDFLinkServiceOptions} options
|
2015-04-28 00:25:32 +09:00
|
|
|
*/
|
2016-04-26 07:57:15 +09:00
|
|
|
function PDFLinkService(options) {
|
|
|
|
options = options || {};
|
|
|
|
this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
|
2015-04-28 00:25:32 +09:00
|
|
|
this.baseUrl = null;
|
|
|
|
this.pdfDocument = null;
|
|
|
|
this.pdfViewer = null;
|
|
|
|
this.pdfHistory = null;
|
|
|
|
|
|
|
|
this._pagesRefCache = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
PDFLinkService.prototype = {
|
|
|
|
setDocument: function PDFLinkService_setDocument(pdfDocument, baseUrl) {
|
|
|
|
this.baseUrl = baseUrl;
|
|
|
|
this.pdfDocument = pdfDocument;
|
|
|
|
this._pagesRefCache = Object.create(null);
|
|
|
|
},
|
|
|
|
|
|
|
|
setViewer: function PDFLinkService_setViewer(pdfViewer) {
|
|
|
|
this.pdfViewer = pdfViewer;
|
|
|
|
},
|
|
|
|
|
|
|
|
setHistory: function PDFLinkService_setHistory(pdfHistory) {
|
|
|
|
this.pdfHistory = pdfHistory;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
|
|
|
get pagesCount() {
|
2016-08-07 20:10:50 +09:00
|
|
|
return this.pdfDocument ? this.pdfDocument.numPages : 0;
|
2015-04-28 00:25:32 +09:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
|
|
|
get page() {
|
|
|
|
return this.pdfViewer.currentPageNumber;
|
|
|
|
},
|
2015-05-29 20:47:28 +09:00
|
|
|
|
2015-04-28 00:25:32 +09:00
|
|
|
/**
|
|
|
|
* @param {number} value
|
|
|
|
*/
|
|
|
|
set page(value) {
|
|
|
|
this.pdfViewer.currentPageNumber = value;
|
|
|
|
},
|
2015-05-29 20:47:28 +09:00
|
|
|
|
2015-04-28 00:25:32 +09:00
|
|
|
/**
|
|
|
|
* @param dest - The PDF destination object.
|
|
|
|
*/
|
|
|
|
navigateTo: function PDFLinkService_navigateTo(dest) {
|
|
|
|
var destString = '';
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
var goToDestination = function(destRef) {
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
// dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..>
|
2015-04-28 00:25:32 +09:00
|
|
|
var pageNumber = destRef instanceof Object ?
|
|
|
|
self._pagesRefCache[destRef.num + ' ' + destRef.gen + ' R'] :
|
|
|
|
(destRef + 1);
|
|
|
|
if (pageNumber) {
|
|
|
|
if (pageNumber > self.pagesCount) {
|
2016-08-07 20:10:50 +09:00
|
|
|
console.error('PDFLinkService_navigateTo: ' +
|
|
|
|
'Trying to navigate to a non-existent page.');
|
|
|
|
return;
|
2015-04-28 00:25:32 +09:00
|
|
|
}
|
|
|
|
self.pdfViewer.scrollPageIntoView(pageNumber, dest);
|
|
|
|
|
2015-05-29 20:37:28 +09:00
|
|
|
if (self.pdfHistory) {
|
|
|
|
// Update the browsing history.
|
|
|
|
self.pdfHistory.push({
|
|
|
|
dest: dest,
|
|
|
|
hash: destString,
|
|
|
|
page: pageNumber
|
|
|
|
});
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
} else {
|
|
|
|
self.pdfDocument.getPageIndex(destRef).then(function (pageIndex) {
|
|
|
|
var pageNum = pageIndex + 1;
|
|
|
|
var cacheKey = destRef.num + ' ' + destRef.gen + ' R';
|
|
|
|
self._pagesRefCache[cacheKey] = pageNum;
|
|
|
|
goToDestination(destRef);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var destinationPromise;
|
|
|
|
if (typeof dest === 'string') {
|
|
|
|
destString = dest;
|
|
|
|
destinationPromise = this.pdfDocument.getDestination(dest);
|
|
|
|
} else {
|
|
|
|
destinationPromise = Promise.resolve(dest);
|
|
|
|
}
|
|
|
|
destinationPromise.then(function(destination) {
|
|
|
|
dest = destination;
|
|
|
|
if (!(destination instanceof Array)) {
|
|
|
|
return; // invalid destination
|
|
|
|
}
|
|
|
|
goToDestination(destination[0]);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param dest - The PDF destination object.
|
|
|
|
* @returns {string} The hyperlink to the PDF object.
|
|
|
|
*/
|
|
|
|
getDestinationHash: function PDFLinkService_getDestinationHash(dest) {
|
|
|
|
if (typeof dest === 'string') {
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
// In practice, a named destination may contain only a number.
|
|
|
|
// If that happens, use the '#nameddest=' form to avoid the link
|
|
|
|
// redirecting to a page, instead of the correct destination.
|
|
|
|
return this.getAnchorUrl(
|
|
|
|
'#' + (isPageNumber(dest) ? 'nameddest=' : '') + escape(dest));
|
2015-04-28 00:25:32 +09:00
|
|
|
}
|
|
|
|
if (dest instanceof Array) {
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
var str = JSON.stringify(dest);
|
|
|
|
return this.getAnchorUrl('#' + escape(str));
|
2015-04-28 00:25:32 +09:00
|
|
|
}
|
2015-12-09 18:07:39 +09:00
|
|
|
return this.getAnchorUrl('');
|
2015-04-28 00:25:32 +09:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prefix the full url on anchor links to make sure that links are resolved
|
|
|
|
* relative to the current URL instead of the one defined in <base href>.
|
|
|
|
* @param {String} anchor The anchor hash, including the #.
|
|
|
|
* @returns {string} The hyperlink to the PDF object.
|
|
|
|
*/
|
|
|
|
getAnchorUrl: function PDFLinkService_getAnchorUrl(anchor) {
|
|
|
|
return (this.baseUrl || '') + anchor;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} hash
|
|
|
|
*/
|
|
|
|
setHash: function PDFLinkService_setHash(hash) {
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
var pageNumber, dest;
|
2015-04-28 00:25:32 +09:00
|
|
|
if (hash.indexOf('=') >= 0) {
|
|
|
|
var params = parseQueryString(hash);
|
2016-05-26 22:24:58 +09:00
|
|
|
if ('search' in params) {
|
|
|
|
this.eventBus.dispatch('findfromurlhash', {
|
|
|
|
source: this,
|
|
|
|
query: params['search'].replace(/"/g, ''),
|
|
|
|
phraseSearch: (params['phrase'] === 'true')
|
|
|
|
});
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
// borrowing syntax from "Parameters for Opening PDF Files"
|
|
|
|
if ('nameddest' in params) {
|
2015-05-29 20:37:28 +09:00
|
|
|
if (this.pdfHistory) {
|
|
|
|
this.pdfHistory.updateNextHashParam(params.nameddest);
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
this.navigateTo(params.nameddest);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ('page' in params) {
|
|
|
|
pageNumber = (params.page | 0) || 1;
|
|
|
|
}
|
|
|
|
if ('zoom' in params) {
|
|
|
|
// Build the destination array.
|
|
|
|
var zoomArgs = params.zoom.split(','); // scale,left,top
|
|
|
|
var zoomArg = zoomArgs[0];
|
|
|
|
var zoomArgNumber = parseFloat(zoomArg);
|
|
|
|
|
|
|
|
if (zoomArg.indexOf('Fit') === -1) {
|
|
|
|
// If the zoomArg is a number, it has to get divided by 100. If it's
|
|
|
|
// a string, it should stay as it is.
|
|
|
|
dest = [null, { name: 'XYZ' },
|
|
|
|
zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
|
|
|
|
zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
|
|
|
|
(zoomArgNumber ? zoomArgNumber / 100 : zoomArg)];
|
|
|
|
} else {
|
|
|
|
if (zoomArg === 'Fit' || zoomArg === 'FitB') {
|
|
|
|
dest = [null, { name: zoomArg }];
|
|
|
|
} else if ((zoomArg === 'FitH' || zoomArg === 'FitBH') ||
|
|
|
|
(zoomArg === 'FitV' || zoomArg === 'FitBV')) {
|
|
|
|
dest = [null, { name: zoomArg },
|
|
|
|
zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null];
|
|
|
|
} else if (zoomArg === 'FitR') {
|
|
|
|
if (zoomArgs.length !== 5) {
|
2015-05-29 20:47:28 +09:00
|
|
|
console.error('PDFLinkService_setHash: ' +
|
2015-04-28 00:25:32 +09:00
|
|
|
'Not enough parameters for \'FitR\'.');
|
|
|
|
} else {
|
|
|
|
dest = [null, { name: zoomArg },
|
|
|
|
(zoomArgs[1] | 0), (zoomArgs[2] | 0),
|
|
|
|
(zoomArgs[3] | 0), (zoomArgs[4] | 0)];
|
|
|
|
}
|
|
|
|
} else {
|
2015-05-29 20:47:28 +09:00
|
|
|
console.error('PDFLinkService_setHash: \'' + zoomArg +
|
2015-04-28 00:25:32 +09:00
|
|
|
'\' is not a valid zoom value.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dest) {
|
|
|
|
this.pdfViewer.scrollPageIntoView(pageNumber || this.page, dest);
|
|
|
|
} else if (pageNumber) {
|
|
|
|
this.page = pageNumber; // simple page
|
|
|
|
}
|
|
|
|
if ('pagemode' in params) {
|
2016-04-26 07:57:15 +09:00
|
|
|
this.eventBus.dispatch('pagemode', {
|
|
|
|
source: this,
|
|
|
|
mode: params.pagemode
|
2015-08-05 05:57:51 +09:00
|
|
|
});
|
2015-04-28 00:25:32 +09:00
|
|
|
}
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
} else if (isPageNumber(hash)) { // Page number.
|
|
|
|
this.page = hash | 0;
|
|
|
|
} else { // Named (or explicit) destination.
|
|
|
|
dest = unescape(hash);
|
|
|
|
try {
|
|
|
|
dest = JSON.parse(dest);
|
|
|
|
} catch (ex) {}
|
|
|
|
|
|
|
|
if (typeof dest === 'string' || isValidExplicitDestination(dest)) {
|
|
|
|
if (this.pdfHistory) {
|
|
|
|
this.pdfHistory.updateNextHashParam(dest);
|
|
|
|
}
|
|
|
|
this.navigateTo(dest);
|
|
|
|
return;
|
2015-05-29 20:37:28 +09:00
|
|
|
}
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
console.error('PDFLinkService_setHash: \'' + unescape(hash) +
|
|
|
|
'\' is not a valid destination.');
|
2015-04-28 00:25:32 +09:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} action
|
|
|
|
*/
|
|
|
|
executeNamedAction: function PDFLinkService_executeNamedAction(action) {
|
|
|
|
// See PDF reference, table 8.45 - Named action
|
|
|
|
switch (action) {
|
|
|
|
case 'GoBack':
|
2015-05-29 20:37:28 +09:00
|
|
|
if (this.pdfHistory) {
|
|
|
|
this.pdfHistory.back();
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'GoForward':
|
2015-05-29 20:37:28 +09:00
|
|
|
if (this.pdfHistory) {
|
|
|
|
this.pdfHistory.forward();
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'NextPage':
|
2016-08-07 20:10:50 +09:00
|
|
|
if (this.page < this.pagesCount) {
|
|
|
|
this.page++;
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'PrevPage':
|
2016-08-07 20:10:50 +09:00
|
|
|
if (this.page > 1) {
|
|
|
|
this.page--;
|
|
|
|
}
|
2015-04-28 00:25:32 +09:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'LastPage':
|
|
|
|
this.page = this.pagesCount;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'FirstPage':
|
|
|
|
this.page = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break; // No action according to spec
|
|
|
|
}
|
|
|
|
|
2016-04-26 07:57:15 +09:00
|
|
|
this.eventBus.dispatch('namedaction', {
|
|
|
|
source: this,
|
2015-04-28 00:25:32 +09:00
|
|
|
action: action
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {number} pageNum - page number.
|
|
|
|
* @param {Object} pageRef - reference to the page.
|
|
|
|
*/
|
|
|
|
cachePageRef: function PDFLinkService_cachePageRef(pageNum, pageRef) {
|
|
|
|
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
|
|
|
|
this._pagesRefCache[refStr] = pageNum;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
[api-minor] Let `LinkAnnotation`/`PDFLinkService_getDestinationHash` return a stringified version of the destination array for explicit destinations
Currently for explicit destinations, compared to named destinations, we manually try to build a hash that often times is a quite poor representation of the *actual* destination. (Currently this only, kind of, works for `\XYZ` destinations.)
For PDF files using explicit destinations, this can make it difficult/impossible to obtain a link to a specific section of the document through the URL.
Note that in practice most PDF files, especially newer ones, use named destinations and these are thus unnaffected by this patch.
This patch also fixes an existing issue in `PDFLinkService_getDestinationHash`, where a named destination consisting of only a number would not be handled correctly.
With the added, and already existing, type checks in place for destinations, I really don't think that this patch exposes any "sensitive" internal destination code not already accessible through normal hash parameters.
*Please note:* Just trying to improve the algorithm that generates the hash is unfortunately not possible in general, since there are a number of cases where it will simply never work well.
- First of all, note that `getDestinationHash` currently relies on the `_pagesRefCache`, hence it's possible that the hash returned is empty during e.g. ranged/streamed loading of a PDF file.
- Second of all, the currently computed hash is actually dependent on the document rotation. With named destinations, the fetched internal destination array is rotational invariant (as it should be), but this will not hold in general for the hash. We can easily avoid this issue by using a stringified destination array.
- Third of all, note that according to the PDF specification[1], `GoToR` destinations may actually contain explicit destination arrays. Since we cannot really construct a hash in `annotation.js`, we currently have no good way to support those. Even though this case seems *very* rare in practice (I've not actually seen such a PDF file), it's in the specification, and this patch allows us to support that for "free".
---
[1] http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf#G11.1951685
2016-05-15 19:12:47 +09:00
|
|
|
function isValidExplicitDestination(dest) {
|
|
|
|
if (!(dest instanceof Array)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
var destLength = dest.length, allowNull = true;
|
|
|
|
if (destLength < 2) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
var page = dest[0];
|
|
|
|
if (!(typeof page === 'object' &&
|
|
|
|
typeof page.num === 'number' && (page.num | 0) === page.num &&
|
|
|
|
typeof page.gen === 'number' && (page.gen | 0) === page.gen) &&
|
|
|
|
!(typeof page === 'number' && (page | 0) === page && page >= 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
var zoom = dest[1];
|
|
|
|
if (!(typeof zoom === 'object' && typeof zoom.name === 'string')) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
switch (zoom.name) {
|
|
|
|
case 'XYZ':
|
|
|
|
if (destLength !== 5) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'Fit':
|
|
|
|
case 'FitB':
|
|
|
|
return destLength === 2;
|
|
|
|
case 'FitH':
|
|
|
|
case 'FitBH':
|
|
|
|
case 'FitV':
|
|
|
|
case 'FitBV':
|
|
|
|
if (destLength !== 3) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'FitR':
|
|
|
|
if (destLength !== 6) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
allowNull = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (var i = 2; i < destLength; i++) {
|
|
|
|
var param = dest[i];
|
|
|
|
if (!(typeof param === 'number' || (allowNull && param === null))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-28 00:25:32 +09:00
|
|
|
return PDFLinkService;
|
|
|
|
})();
|
2016-04-09 02:34:27 +09:00
|
|
|
|
|
|
|
var SimpleLinkService = (function SimpleLinkServiceClosure() {
|
|
|
|
function SimpleLinkService() {}
|
|
|
|
|
|
|
|
SimpleLinkService.prototype = {
|
|
|
|
/**
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
|
|
|
get page() {
|
|
|
|
return 0;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* @param {number} value
|
|
|
|
*/
|
|
|
|
set page(value) {},
|
|
|
|
/**
|
|
|
|
* @param dest - The PDF destination object.
|
|
|
|
*/
|
|
|
|
navigateTo: function (dest) {},
|
|
|
|
/**
|
|
|
|
* @param dest - The PDF destination object.
|
|
|
|
* @returns {string} The hyperlink to the PDF object.
|
|
|
|
*/
|
|
|
|
getDestinationHash: function (dest) {
|
|
|
|
return '#';
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* @param hash - The PDF parameters/hash.
|
|
|
|
* @returns {string} The hyperlink to the PDF object.
|
|
|
|
*/
|
|
|
|
getAnchorUrl: function (hash) {
|
|
|
|
return '#';
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* @param {string} hash
|
|
|
|
*/
|
|
|
|
setHash: function (hash) {},
|
|
|
|
/**
|
|
|
|
* @param {string} action
|
|
|
|
*/
|
|
|
|
executeNamedAction: function (action) {},
|
|
|
|
/**
|
|
|
|
* @param {number} pageNum - page number.
|
|
|
|
* @param {Object} pageRef - reference to the page.
|
|
|
|
*/
|
|
|
|
cachePageRef: function (pageNum, pageRef) {}
|
|
|
|
};
|
|
|
|
return SimpleLinkService;
|
|
|
|
})();
|
|
|
|
|
|
|
|
exports.PDFLinkService = PDFLinkService;
|
|
|
|
exports.SimpleLinkService = SimpleLinkService;
|
|
|
|
}));
|