3 Copyright(c)2008 Internet Archive. Software license AGPL version 3.
5 This file is part of GnuBook.
7 GnuBook 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 GnuBook 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 GnuBook. If not, see <http://www.gnu.org/licenses/>.
21 $id = $_REQUEST['id'];
22 $itemPath = $_REQUEST['itemPath'];
23 $subPrefix = $_REQUEST['subPrefix'];
24 $server = $_REQUEST['server'];
26 // Check if we're on a dev vhost and point to JSIA in the user's public_html on the datanode
27 // $$$ TODO consolidate this logic
28 if (strpos($_SERVER["REQUEST_URI"], "/~mang") === 0) { // Serving out of home dir
29 $server .= ':80/~mang';
30 } else if (strpos($_SERVER["REQUEST_URI"], "/~testflip") === 0) { // Serving out of home dir
31 $server .= ':80/~testflip';
35 $subItemPath = $itemPath . '/' . $subPrefix;
37 $subItemPath = $itemPath . '/' . $id;
41 GBFatal("No identifier specified!");
44 if ("" == $itemPath) {
45 GBFatal("No itemPath specified!");
49 GBFatal("No server specified!");
52 if (!preg_match("|^/[0-3]/items/{$id}$|", $itemPath)) {
56 // XXX check here that subitem is okay
58 $imageFormat = 'unknown';
59 $zipFile = "${subItemPath}_jp2.zip";
61 if (file_exists($zipFile)) {
64 $zipFile = "${subItemPath}_tif.zip";
65 if (file_exists($zipFile)) {
70 if ("unknown" == $imageFormat) {
71 GBfatal("Unknown image format");
74 $scanDataFile = "${subItemPath}_scandata.xml";
75 $scanDataZip = "$itemPath/scandata.zip";
76 if (file_exists($scanDataFile)) {
77 $scanData = simplexml_load_file($scanDataFile);
78 } else if (file_exists($scanDataZip)) {
79 $cmd = 'unzip -p ' . escapeshellarg($scanDataZip) . ' scandata.xml';
80 exec($cmd, $output, $retval);
81 if ($retval != 0) GBFatal("Could not unzip ScanData!");
83 $dump = join("\n", $output);
84 $scanData = simplexml_load_string($dump);
85 } else if (file_exists("$itemPath/scandata.xml")) {
86 // For e.g. Scribe v.0 books!
87 $scanData = simplexml_load_file("$itemPath/scandata.xml");
89 GBFatal("ScanData file not found!");
92 $metaDataFile = "$itemPath/{$id}_meta.xml";
93 if (!file_exists($metaDataFile)) {
94 GBFatal("MetaData file not found!");
98 $metaData = simplexml_load_file($metaDataFile);
100 //$firstLeaf = $scanData->pageData->page[0]['leafNum'];
106 /* Output title leaf if marked */
108 foreach ($scanData->pageData->page as $page) {
109 if (("Title Page" == $page->pageType) || ("Title" == $page->pageType)) {
110 $titleLeaf = "{$page['leafNum']}";
115 if ('' != $titleLeaf) {
116 printf("gb.titleLeaf = %d;\n", $titleLeaf);
120 gb.getPageWidth = function(index) {
121 //return parseInt(this.pageW[index]/this.reduce);
124 if (index < 0) { // Synthesize
125 return this.pageW[0];
126 } else if (index >= this.numLeafs) {
127 return this.pageW[this.numLeafs - 1];
130 return this.pageW[index];
133 gb.getPageHeight = function(index) {
134 //return parseInt(this.pageH[index]/this.reduce);
137 if (index < 0) { // Synthesize
138 return this.pageH[0];
139 } else if (index >= gb.numLeafs) {
140 return this.pageH[gb.numLeafs - 1];
143 return this.pageH[index];
146 // Returns true if page image is available rotated
147 gb.canRotatePage = function(index) {
148 return 'jp2' == this.imageFormat; // Assume single format for now
151 // reduce defaults to 1 (no reduction)
152 // rotate defaults to 0 (no rotation)
153 gb.getPageURI = function(index, reduce, rotate) {
156 if (index < 0 || index >= this.numLeafs) { // Synthesize page
157 return "/bookreader/images/transparent.png";
163 if ('undefined' == typeof(reduce)) {
168 if ('undefined' == typeof(rotate)) {
174 var file = this._getPageFile(index);
176 // $$$ add more image stack formats here
178 var url = 'http://'+this.server+'/GnuBook/GnuBookImages.php?zip='+this.zip+'&file='+file+'&scale='+_reduce+'&rotate='+_rotate;
180 if ('undefined' == typeof(reduce)) {
181 // reduce not passed in
182 var ratio = this.getPageHeight(index) / this.twoPage.height;
184 // $$$ we make an assumption here that the scales are available pow2 (like kakadu)
187 } else if (ratio < 4) {
189 } else if (ratio < 8) {
191 } else if (ratio < 16) {
193 } else if (ratio < 32) {
201 var url = 'http://'+this.server+'/GnuBook/GnuBookImages.php?zip='+this.zip+'&file='+file+'&scale='+_reduce+'&rotate='+_rotate;
207 gb._getPageFile = function(index) {
208 var leafStr = '0000';
209 var imgStr = this.leafMap[index].toString();
210 var re = new RegExp("0{"+imgStr.length+"}$");
212 var insideZipPrefix = this.subPrefix.match('[^/]+$');
213 var file = insideZipPrefix + '_' + this.imageFormat + '/' + insideZipPrefix + '_' + leafStr.replace(re, imgStr) + '.' + this.imageFormat;
218 gb.getPageSide = function(index) {
219 //assume the book starts with a cover (right-hand leaf)
220 //we should really get handside from scandata.xml
222 <? // Use special function if we should infer the page sides based off the title page index
223 if (preg_match('/goog$/', $id) && ('' != $titleLeaf)) {
225 // assume page side based on title pagex
226 var titleIndex = gb.leafNumToIndex(gb.titleLeaf);
227 // assume title page is RHS
228 var delta = titleIndex - index;
229 if (0 == (delta & 0x1)) {
239 // $$$ we should get this from scandata instead of assuming the accessible
240 // leafs are contiguous
241 if ('rl' != this.pageProgression) {
242 // If pageProgression is not set RTL we assume it is LTR
243 if (0 == (index & 0x1)) {
244 // Even-numbered page
252 if (0 == (index & 0x1)) {
260 gb.getPageNum = function(index) {
261 var pageNum = this.pageNums[index];
269 gb.leafNumToIndex = function(leafNum) {
270 var index = jQuery.inArray(leafNum, this.leafMap);
278 // This function returns the left and right indices for the user-visible
279 // spread that contains the given index. The return values may be
280 // null if there is no facing page or the index is invalid.
281 gb.getSpreadIndices = function(pindex) {
282 // $$$ we could make a separate function for the RTL case and
283 // only bind it if necessary instead of always checking
284 // $$$ we currently assume there are no gaps
286 var spreadIndices = [null, null];
287 if ('rl' == this.pageProgression) {
289 if (this.getPageSide(pindex) == 'R') {
290 spreadIndices[1] = pindex;
291 spreadIndices[0] = pindex + 1;
293 // Given index was LHS
294 spreadIndices[0] = pindex;
295 spreadIndices[1] = pindex - 1;
299 if (this.getPageSide(pindex) == 'L') {
300 spreadIndices[0] = pindex;
301 spreadIndices[1] = pindex + 1;
303 // Given index was RHS
304 spreadIndices[1] = pindex;
305 spreadIndices[0] = pindex - 1;
309 //console.log(" index %d mapped to spread %d,%d", pindex, spreadIndices[0], spreadIndices[1]);
311 return spreadIndices;
314 // Remove the page number assertions for all but the highest index page with
315 // a given assertion. Ensures there is only a single page "{pagenum}"
316 // e.g. the last page asserted as page 5 retains that assertion.
317 gb.uniquifyPageNums = function() {
320 for (var i = gb.pageNums.length - 1; i--; i >= 0) {
321 var pageNum = gb.pageNums[i];
322 if ( !seen[pageNum] ) {
323 seen[pageNum] = true;
325 gb.pageNums[i] = null;
331 gb.cleanupMetadata = function() {
332 gb.uniquifyPageNums();
337 // Returns a URL for an embedded version of the current book
338 gb.getEmbedURL = function() {
339 // We could generate a URL hash fragment here but for now we just leave at defaults
340 var url = 'http://' + window.location.host + '/stream/'+this.bookId;
341 if (this.subPrefix != this.bookId) { // Only include if needed
342 url += '/' + this.subPrefix;
350 // Returns the embed code HTML fragment suitable for copy and paste
351 gb.getEmbedCode = function() {
352 return "<iframe src='" + this.getEmbedURL() + "' width='480px' height='430px'></iframe>";
358 foreach ($scanData->pageData->page as $page) {
359 if (shouldAddPage($page)) {
360 if(0 != $i) echo ","; //stupid IE
361 echo "{$page->cropBox->w}";
372 foreach ($scanData->pageData->page as $page) {
373 if (shouldAddPage($page)) {
374 if(0 != $i) echo ","; //stupid IE
375 echo "{$page->cropBox->h}";
376 $totalHeight += intval($page->cropBox->h/4) + 10;
385 foreach ($scanData->pageData->page as $page) {
386 if (shouldAddPage($page)) {
387 if(0 != $i) echo ","; //stupid IE
388 echo "{$page['leafNum']}";
398 foreach ($scanData->pageData->page as $page) {
399 if (shouldAddPage($page)) {
400 if(0 != $i) echo ","; //stupid IE
401 if (array_key_exists('pageNumber', $page) && ('' != $page->pageNumber)) {
402 echo "'{$page->pageNumber}'";
413 gb.numLeafs = gb.pageW.length;
415 gb.bookId = '<?echo $id;?>';
416 gb.zip = '<?echo $zipFile;?>';
417 gb.subPrefix = '<?echo $subPrefix;?>';
418 gb.server = '<?echo $server;?>';
419 gb.bookTitle= '<?echo preg_replace("/\'/", "\\'", $metaData->title);?>';
420 gb.bookPath = '<?echo $subItemPath;?>';
421 gb.bookUrl = '<?echo "http://www.archive.org/details/$id";?>';
422 gb.imageFormat = '<?echo $imageFormat;?>';
426 # Load some values from meta.xml
427 if ('' != $metaData->{'page-progression'}) {
428 echo "gb.pageProgression = '" . $metaData->{"page-progression"} . "';";
430 // Assume page progression is Left To Right
431 echo "gb.pageProgression = 'lr';";
435 if ('bandersnatchhsye00scarrich' == $id) {
436 echo "gb.mode = 2;\n";
437 echo "gb.auto = true;\n";
442 // Check for config object
443 // $$$ change this to use the newer params object
444 if (typeof(gbConfig) != 'undefined') {
445 if (typeof(gbConfig["ui"]) != 'undefined') {
446 gb.ui = gbConfig["ui"];
449 if (gbConfig['mode'] == 1) {
451 if (typeof(gbConfig['reduce'] != 'undefined')) {
452 gb.reduce = gbConfig['reduce'];
454 } else if (gbConfig['mode'] == 2) {
458 //$$$mang hack to override request for 2up for books with attribution page
459 // as first page until we can display that page in 2up
461 if (strrpos($id, $needle) === strlen($id)-strlen($needle)) {
462 print "// override for books with attribution page\n";
463 print "gb.mode = 1;\n";
469 gb.cleanupMetadata();
475 function GBFatal($string) {
476 echo "alert('$string')\n";
480 // Returns true if a page should be added based on it's information in
482 function shouldAddPage($page) {
483 // Return false only if the page is marked addToAccessFormats false.
484 // If there is no assertion we assume it should be added.
485 if (isset($page->addToAccessFormats)) {
486 if ("false" == strtolower(trim($page->addToAccessFormats))) {