3 Copyright(c)2008 Internet Archive. Software license AGPL version 3.
5 This file is part of BookReader.
7 BookReader is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Affero General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 BookReader is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Affero General Public License for more details.
17 You should have received a copy of the GNU Affero General Public License
18 along with BookReader. If not, see <http://www.gnu.org/licenses/>.
21 header('Content-Type: application/javascript');
23 $id = $_REQUEST['id'];
24 $itemPath = $_REQUEST['itemPath'];
25 $subPrefix = $_REQUEST['subPrefix'];
26 $server = $_REQUEST['server'];
28 // $$$mang this code has been refactored into BookReaderMeta.inc.php for use e.g. by
29 // BookReaderPreview.php and BookReaderImages.php. The code below should be
30 // taken out and replaced by calls into BookReaderMeta
32 // Check if we're on a dev vhost and point to JSIA in the user's public_html on the datanode
34 // $$$ TODO consolidate this logic
35 if (strpos($_SERVER["REQUEST_URI"], "/~mang") === 0) { // Serving out of home dir
36 $server .= ':80/~mang';
37 } else if (strpos($_SERVER["REQUEST_URI"], "/~rkumar") === 0) { // Serving out of home dir
38 $server .= ':80/~rkumar';
39 } else if (strpos($_SERVER["REQUEST_URI"], "/~testflip") === 0) { // Serving out of home dir
40 $server .= ':80/~testflip';
41 } else if (strpos($_SERVER["REQUEST_URI"], "/~mccabe") === 0) { // Serving out of home dir
42 $server .= ':80/~mccabe';
48 $subItemPath = $itemPath . '/' . $subPrefix;
51 BRFatal("No identifier specified!");
54 if ("" == $itemPath) {
55 BRFatal("No itemPath specified!");
59 BRFatal("No server specified!");
62 if (!preg_match("|^/\d+/items/{$id}$|", $itemPath)) {
66 // XXX check here that subitem is okay
68 $filesDataFile = "$itemPath/${id}_files.xml";
70 if (file_exists($filesDataFile)) {
71 $filesData = simplexml_load_file("$itemPath/${id}_files.xml");
73 BRfatal("File metadata not found!");
76 $imageStackInfo = findImageStack($subPrefix, $filesData);
77 if ($imageStackInfo['imageFormat'] == 'unknown') {
78 BRfatal('Couldn\'t find image stack');
81 $imageFormat = $imageStackInfo['imageFormat'];
82 $archiveFormat = $imageStackInfo['archiveFormat'];
83 $imageStackFile = $itemPath . "/" . $imageStackInfo['imageStackFile'];
85 if ("unknown" == $imageFormat) {
86 BRfatal("Unknown image format");
89 if ("unknown" == $archiveFormat) {
90 BRfatal("Unknown archive format");
94 $scanDataFile = "${subItemPath}_scandata.xml";
95 $scanDataZip = "$itemPath/scandata.zip";
96 if (file_exists($scanDataFile)) {
97 $scanData = simplexml_load_file($scanDataFile);
98 } else if (file_exists($scanDataZip)) {
99 $cmd = 'unzip -p ' . escapeshellarg($scanDataZip) . ' scandata.xml';
100 exec($cmd, $output, $retval);
101 if ($retval != 0) BRFatal("Could not unzip ScanData!");
103 $dump = join("\n", $output);
104 $scanData = simplexml_load_string($dump);
105 } else if (file_exists("$itemPath/scandata.xml")) {
106 // For e.g. Scribe v.0 books!
107 $scanData = simplexml_load_file("$itemPath/scandata.xml");
109 BRFatal("ScanData file not found!");
112 $metaDataFile = "$itemPath/{$id}_meta.xml";
113 if (!file_exists($metaDataFile)) {
114 BRFatal("MetaData file not found!");
118 $metaData = simplexml_load_file($metaDataFile);
120 //$firstLeaf = $scanData->pageData->page[0]['leafNum'];
123 br = new BookReader();
126 /* Output title leaf if marked */
128 foreach ($scanData->pageData->page as $page) {
129 if (("Title Page" == $page->pageType) || ("Title" == $page->pageType)) {
130 $titleLeaf = "{$page['leafNum']}";
135 if ('' != $titleLeaf) {
136 printf("br.titleLeaf = %d;\n", $titleLeaf);
140 br.getPageWidth = function(index) {
141 return this.pageW[index];
144 br.getPageHeight = function(index) {
145 return this.pageH[index];
148 // Returns true if page image is available rotated
149 br.canRotatePage = function(index) {
150 return 'jp2' == this.imageFormat; // Assume single format for now
153 // reduce defaults to 1 (no reduction)
154 // rotate defaults to 0 (no rotation)
155 br.getPageURI = function(index, reduce, rotate) {
159 if ('undefined' == typeof(reduce)) {
164 if ('undefined' == typeof(rotate)) {
170 var file = this._getPageFile(index);
172 // $$$ add more image stack formats here
173 return 'http://'+this.server+'/BookReader/BookReaderImages.php?zip='+this.zip+'&file='+file+'&scale='+_reduce+'&rotate='+_rotate;
176 br._getPageFile = function(index) {
177 var leafStr = '0000';
178 var imgStr = this.leafMap[index].toString();
179 var re = new RegExp("0{"+imgStr.length+"}$");
181 var insideZipPrefix = this.subPrefix.match('[^/]+$');
182 var file = insideZipPrefix + '_' + this.imageFormat + '/' + insideZipPrefix + '_' + leafStr.replace(re, imgStr) + '.' + this.imageFormat;
187 br.getPageSide = function(index) {
188 //assume the book starts with a cover (right-hand leaf)
189 //we should really get handside from scandata.xml
191 <? // Use special function if we should infer the page sides based off the title page index
192 if (preg_match('/goog$/', $id) && ('' != $titleLeaf)) {
194 // assume page side based on title pagex
195 var titleIndex = br.leafNumToIndex(br.titleLeaf);
196 // assume title page is RHS
197 var delta = titleIndex - index;
198 if (0 == (delta & 0x1)) {
208 // $$$ we should get this from scandata instead of assuming the accessible
209 // leafs are contiguous
210 if ('rl' != this.pageProgression) {
211 // If pageProgression is not set RTL we assume it is LTR
212 if (0 == (index & 0x1)) {
213 // Even-numbered page
221 if (0 == (index & 0x1)) {
229 br.getPageNum = function(index) {
230 var pageNum = this.pageNums[index];
238 // Single images in the Internet Archive scandata.xml metadata are (somewhat incorrectly)
239 // given a "leaf" number. Some of these images from the scanning process should not
240 // be displayed in the BookReader (for example colour calibration cards). Since some
241 // of the scanned images will not be displayed in the BookReader (those marked with
242 // addToAccessFormats false in the scandata.xml) leaf numbers and BookReader page
243 // indexes are generally not the same. This function returns the BookReader page
244 // index given a scanned leaf number.
246 // This function is used, for example, to map between search results (that use the
247 // leaf numbers) and the displayed pages in the BookReader.
248 br.leafNumToIndex = function(leafNum) {
249 for (var index = 0; index < this.leafMap.length; index++) {
250 if (this.leafMap[index] == leafNum) {
258 // This function returns the left and right indices for the user-visible
259 // spread that contains the given index. The return values may be
260 // null if there is no facing page or the index is invalid.
261 br.getSpreadIndices = function(pindex) {
262 // $$$ we could make a separate function for the RTL case and
263 // only bind it if necessary instead of always checking
264 // $$$ we currently assume there are no gaps
266 var spreadIndices = [null, null];
267 if ('rl' == this.pageProgression) {
269 if (this.getPageSide(pindex) == 'R') {
270 spreadIndices[1] = pindex;
271 spreadIndices[0] = pindex + 1;
273 // Given index was LHS
274 spreadIndices[0] = pindex;
275 spreadIndices[1] = pindex - 1;
279 if (this.getPageSide(pindex) == 'L') {
280 spreadIndices[0] = pindex;
281 spreadIndices[1] = pindex + 1;
283 // Given index was RHS
284 spreadIndices[1] = pindex;
285 spreadIndices[0] = pindex - 1;
289 //console.log(" index %d mapped to spread %d,%d", pindex, spreadIndices[0], spreadIndices[1]);
291 return spreadIndices;
294 // Remove the page number assertions for all but the highest index page with
295 // a given assertion. Ensures there is only a single page "{pagenum}"
296 // e.g. the last page asserted as page 5 retains that assertion.
297 br.uniquifyPageNums = function() {
300 for (var i = br.pageNums.length - 1; i--; i >= 0) {
301 var pageNum = br.pageNums[i];
302 if ( !seen[pageNum] ) {
303 seen[pageNum] = true;
305 br.pageNums[i] = null;
311 br.cleanupMetadata = function() {
312 br.uniquifyPageNums();
317 // Returns a URL for an embedded version of the current book
318 br.getEmbedURL = function() {
319 // We could generate a URL hash fragment here but for now we just leave at defaults
320 var url = 'http://' + window.location.host + '/stream/'+this.bookId;
321 if (this.subPrefix != this.bookId) { // Only include if needed
322 url += '/' + this.subPrefix;
330 // Returns the embed code HTML fragment suitable for copy and paste
331 br.getEmbedCode = function() {
332 return "<iframe src='" + this.getEmbedURL() + "' width='480px' height='430px'></iframe>";
338 foreach ($scanData->pageData->page as $page) {
339 if (shouldAddPage($page)) {
340 if(0 != $i) echo ","; //stupid IE
341 echo "{$page->cropBox->w}";
352 foreach ($scanData->pageData->page as $page) {
353 if (shouldAddPage($page)) {
354 if(0 != $i) echo ","; //stupid IE
355 echo "{$page->cropBox->h}";
356 $totalHeight += intval($page->cropBox->h/4) + 10;
365 foreach ($scanData->pageData->page as $page) {
366 if (shouldAddPage($page)) {
367 if(0 != $i) echo ","; //stupid IE
368 echo "{$page['leafNum']}";
378 foreach ($scanData->pageData->page as $page) {
379 if (shouldAddPage($page)) {
380 if(0 != $i) echo ","; //stupid IE
381 if (array_key_exists('pageNumber', $page) && ('' != $page->pageNumber)) {
382 echo "'{$page->pageNumber}'";
393 br.numLeafs = br.pageW.length;
395 br.bookId = '<?echo $id;?>';
396 br.zip = '<?echo $imageStackFile;?>';
397 br.subPrefix = '<?echo $subPrefix;?>';
398 br.server = '<?echo $server;?>';
399 br.bookTitle= '<?echo preg_replace("/\'/", "\\'", $metaData->title);?>';
400 br.bookPath = '<?echo $subItemPath;?>';
401 br.bookUrl = '<?echo "http://www.archive.org/details/$id";?>';
402 br.imageFormat = '<?echo $imageFormat;?>';
403 br.archiveFormat = '<?echo $archiveFormat;?>';
407 # Load some values from meta.xml
408 if ('' != $metaData->{'page-progression'}) {
409 echo "br.pageProgression = '" . $metaData->{"page-progression"} . "';";
411 // Assume page progression is Left To Right
412 echo "br.pageProgression = 'lr';";
416 if ('bandersnatchhsye00scarrich' == $id) {
417 echo "br.mode = 2;\n";
418 echo "br.auto = true;\n";
423 // Check for config object
424 // $$$ change this to use the newer params object
425 if (typeof(brConfig) != 'undefined') {
426 if (typeof(brConfig["ui"]) != 'undefined') {
427 br.ui = brConfig["ui"];
430 if (brConfig['mode'] == 1) {
432 if (typeof(brConfig['reduce'] != 'undefined')) {
433 br.reduce = brConfig['reduce'];
435 } else if (brConfig['mode'] == 2) {
439 //$$$mang hack to override request for 2up for books with attribution page
440 // as first page until we can display that page in 2up
442 if (strrpos($id, $needle) === strlen($id)-strlen($needle)) {
443 print "// override for books with attribution page\n";
444 print "br.mode = 1;\n";
450 br.cleanupMetadata();
456 function BRFatal($string) {
457 // $$$ TODO log error
458 echo "alert('$string')\n";
462 // Returns true if a page should be added based on it's information in
464 function shouldAddPage($page) {
465 // Return false only if the page is marked addToAccessFormats false.
466 // If there is no assertion we assume it should be added.
467 if (isset($page->addToAccessFormats)) {
468 if ("false" == strtolower(trim($page->addToAccessFormats))) {
476 // Returns { 'imageFormat' => , 'archiveFormat' => '} given a sub-item prefix and loaded xml data
477 function findImageStack($subPrefix, $filesData) {
479 // $$$ The order of the image formats determines which will be returned first
480 $imageFormats = array('JP2' => 'jp2', 'TIFF' => 'tif', 'JPEG' => 'jpg');
481 $archiveFormats = array('ZIP' => 'zip', 'Tar' => 'tar');
482 $imageGroup = implode('|', array_keys($imageFormats));
483 $archiveGroup = implode('|', array_keys($archiveFormats));
484 // $$$ Currently only return processed images
485 $imageStackRegex = "/Single Page (Processed) (${imageGroup}) (${archiveGroup})/";
487 foreach ($filesData->file as $file) {
488 if (strpos($file['name'], $subPrefix) === 0) { // subprefix matches beginning
489 if (preg_match($imageStackRegex, $file->format, $matches)) {
491 // Make sure we have a regular image stack
492 $imageFormat = $imageFormats[$matches[2]];
493 if (strpos($file['name'], $subPrefix . '_' . $imageFormat) === 0) {
494 return array('imageFormat' => $imageFormat,
495 'archiveFormat' => $archiveFormats[$matches[3]],
496 'imageStackFile' => $file['name']);
502 return array('imageFormat' => 'unknown', 'archiveFormat' => 'unknown', 'imageStackFile' => 'unknown');