. */ header('Content-Type: application/javascript'); $id = $_REQUEST['id']; $itemPath = $_REQUEST['itemPath']; $subPrefix = $_REQUEST['subPrefix']; $server = $_REQUEST['server']; // $$$mang this code has been refactored into BookReaderMeta.inc.php for use e.g. by // BookReaderPreview.php and BookReaderImages.php. The code below should be // taken out and replaced by calls into BookReaderMeta // Check if we're on a dev vhost and point to JSIA in the user's public_html on the datanode // $$$ TODO consolidate this logic if (strpos($_SERVER["REQUEST_URI"], "/~mang") === 0) { // Serving out of home dir $server .= ':80/~mang'; } else if (strpos($_SERVER["REQUEST_URI"], "/~rkumar") === 0) { // Serving out of home dir $server .= ':80/~rkumar'; } else if (strpos($_SERVER["REQUEST_URI"], "/~testflip") === 0) { // Serving out of home dir $server .= ':80/~testflip'; } if (! $subPrefix) { $subPrefix = $id; } $subItemPath = $itemPath . '/' . $subPrefix; if ("" == $id) { BRFatal("No identifier specified!"); } if ("" == $itemPath) { BRFatal("No itemPath specified!"); } if ("" == $server) { BRFatal("No server specified!"); } if (!preg_match("|^/\d+/items/{$id}$|", $itemPath)) { BRFatal("Bad id!"); } // XXX check here that subitem is okay $filesDataFile = "$itemPath/${id}_files.xml"; if (file_exists($filesDataFile)) { $filesData = simplexml_load_file("$itemPath/${id}_files.xml"); } else { BRfatal("File metadata not found!"); } $imageStackInfo = findImageStack($subPrefix, $filesData); if ($imageStackInfo['imageFormat'] == 'unknown') { BRfatal('Couldn\'t find image stack'); } $imageFormat = $imageStackInfo['imageFormat']; $archiveFormat = $imageStackInfo['archiveFormat']; $imageStackFile = $itemPath . "/" . $imageStackInfo['imageStackFile']; if ("unknown" == $imageFormat) { BRfatal("Unknown image format"); } if ("unknown" == $archiveFormat) { BRfatal("Unknown archive format"); } $scanDataFile = "${subItemPath}_scandata.xml"; $scanDataZip = "$itemPath/scandata.zip"; if (file_exists($scanDataFile)) { $scanData = simplexml_load_file($scanDataFile); } else if (file_exists($scanDataZip)) { $cmd = 'unzip -p ' . escapeshellarg($scanDataZip) . ' scandata.xml'; exec($cmd, $output, $retval); if ($retval != 0) BRFatal("Could not unzip ScanData!"); $dump = join("\n", $output); $scanData = simplexml_load_string($dump); } else if (file_exists("$itemPath/scandata.xml")) { // For e.g. Scribe v.0 books! $scanData = simplexml_load_file("$itemPath/scandata.xml"); } else { BRFatal("ScanData file not found!"); } $metaDataFile = "$itemPath/{$id}_meta.xml"; if (!file_exists($metaDataFile)) { BRFatal("MetaData file not found!"); } $metaData = simplexml_load_file($metaDataFile); //$firstLeaf = $scanData->pageData->page[0]['leafNum']; ?> br = new BookReader(); pageData->page as $page) { if (("Title Page" == $page->pageType) || ("Title" == $page->pageType)) { $titleLeaf = "{$page['leafNum']}"; break; } } if ('' != $titleLeaf) { printf("br.titleLeaf = %d;\n", $titleLeaf); } ?> br.getPageWidth = function(index) { return this.pageW[index]; } br.getPageHeight = function(index) { return this.pageH[index]; } // Returns true if page image is available rotated br.canRotatePage = function(index) { return 'jp2' == this.imageFormat; // Assume single format for now } // reduce defaults to 1 (no reduction) // rotate defaults to 0 (no rotation) br.getPageURI = function(index, reduce, rotate) { var _reduce; var _rotate; if ('undefined' == typeof(reduce)) { _reduce = 1; } else { _reduce = reduce; } if ('undefined' == typeof(rotate)) { _rotate = 0; } else { _rotate = rotate; } var file = this._getPageFile(index); // $$$ add more image stack formats here return 'http://'+this.server+'/BookReader/BookReaderImages.php?zip='+this.zip+'&file='+file+'&scale='+_reduce+'&rotate='+_rotate; } br._getPageFile = function(index) { var leafStr = '0000'; var imgStr = this.leafMap[index].toString(); var re = new RegExp("0{"+imgStr.length+"}$"); var insideZipPrefix = this.subPrefix.match('[^/]+$'); var file = insideZipPrefix + '_' + this.imageFormat + '/' + insideZipPrefix + '_' + leafStr.replace(re, imgStr) + '.' + this.imageFormat; return file; } br.getPageSide = function(index) { //assume the book starts with a cover (right-hand leaf) //we should really get handside from scandata.xml // assume page side based on title pagex var titleIndex = br.leafNumToIndex(br.titleLeaf); // assume title page is RHS var delta = titleIndex - index; if (0 == (delta & 0x1)) { // even delta return 'R'; } else { return 'L'; } // $$$ we should get this from scandata instead of assuming the accessible // leafs are contiguous if ('rl' != this.pageProgression) { // If pageProgression is not set RTL we assume it is LTR if (0 == (index & 0x1)) { // Even-numbered page return 'R'; } else { // Odd-numbered page return 'L'; } } else { // RTL if (0 == (index & 0x1)) { return 'L'; } else { return 'R'; } } } br.getPageNum = function(index) { var pageNum = this.pageNums[index]; if (pageNum) { return pageNum; } else { return 'n' + index; } } // Single images in the Internet Archive scandata.xml metadata are (somewhat incorrectly) // given a "leaf" number. Some of these images from the scanning process should not // be displayed in the BookReader (for example colour calibration cards). Since some // of the scanned images will not be displayed in the BookReader (those marked with // addToAccessFormats false in the scandata.xml) leaf numbers and BookReader page // indexes are generally not the same. This function returns the BookReader page // index given a scanned leaf number. // // This function is used, for example, to map between search results (that use the // leaf numbers) and the displayed pages in the BookReader. br.leafNumToIndex = function(leafNum) { for (var index = 0; index < this.leafMap.length; index++) { if (this.leafMap[index] == leafNum) { return index; } } return null; } // This function returns the left and right indices for the user-visible // spread that contains the given index. The return values may be // null if there is no facing page or the index is invalid. br.getSpreadIndices = function(pindex) { // $$$ we could make a separate function for the RTL case and // only bind it if necessary instead of always checking // $$$ we currently assume there are no gaps var spreadIndices = [null, null]; if ('rl' == this.pageProgression) { // Right to Left if (this.getPageSide(pindex) == 'R') { spreadIndices[1] = pindex; spreadIndices[0] = pindex + 1; } else { // Given index was LHS spreadIndices[0] = pindex; spreadIndices[1] = pindex - 1; } } else { // Left to right if (this.getPageSide(pindex) == 'L') { spreadIndices[0] = pindex; spreadIndices[1] = pindex + 1; } else { // Given index was RHS spreadIndices[1] = pindex; spreadIndices[0] = pindex - 1; } } //console.log(" index %d mapped to spread %d,%d", pindex, spreadIndices[0], spreadIndices[1]); return spreadIndices; } // Remove the page number assertions for all but the highest index page with // a given assertion. Ensures there is only a single page "{pagenum}" // e.g. the last page asserted as page 5 retains that assertion. br.uniquifyPageNums = function() { var seen = {}; for (var i = br.pageNums.length - 1; i--; i >= 0) { var pageNum = br.pageNums[i]; if ( !seen[pageNum] ) { seen[pageNum] = true; } else { br.pageNums[i] = null; } } } br.cleanupMetadata = function() { br.uniquifyPageNums(); } // getEmbedURL //________ // Returns a URL for an embedded version of the current book br.getEmbedURL = function() { // We could generate a URL hash fragment here but for now we just leave at defaults var url = 'http://' + window.location.host + '/stream/'+this.bookId; if (this.subPrefix != this.bookId) { // Only include if needed url += '/' + this.subPrefix; } url += '?ui=embed'; return url; } // getEmbedCode //________ // Returns the embed code HTML fragment suitable for copy and paste br.getEmbedCode = function() { return ""; } // getOpenLibraryRecord br.getOpenLibraryRecord = function(callback) { // Try looking up by ocaid first, then by source_record var jsonURL = 'http://openlibrary.org/query.json?type=/type/edition&*=&ocaid=' + br.bookId; $.ajax({ url: jsonURL, success: function(data) { if (data && data.length > 0) { callback(br, data[0]); } else { // try sourceid jsonURL = 'http://openlibrary.org/query.json?type=/type/edition&*=&source_records=ia:' + br.bookId; $.ajax({ url: jsonURL, success: function(data) { if (data && data.length > 0) { callback(br, data[0]); } }, dataType: 'jsonp' }); } }, dataType: 'jsonp' }); } br.pageW = [ pageData->page as $page) { if (shouldAddPage($page)) { if(0 != $i) echo ","; //stupid IE echo "{$page->cropBox->w}"; $i++; } } ?> ]; br.pageH = [ pageData->page as $page) { if (shouldAddPage($page)) { if(0 != $i) echo ","; //stupid IE echo "{$page->cropBox->h}"; $totalHeight += intval($page->cropBox->h/4) + 10; $i++; } } ?> ]; br.leafMap = [ pageData->page as $page) { if (shouldAddPage($page)) { if(0 != $i) echo ","; //stupid IE echo "{$page['leafNum']}"; $i++; } } ?> ]; br.pageNums = [ pageData->page as $page) { if (shouldAddPage($page)) { if(0 != $i) echo ","; //stupid IE if (array_key_exists('pageNumber', $page) && ('' != $page->pageNumber)) { echo "'{$page->pageNumber}'"; } else { echo "null"; } $i++; } } ?> ]; br.numLeafs = br.pageW.length; br.bookId = ''; br.zip = ''; br.subPrefix = ''; br.server = ''; br.bookTitle= 'title);?>'; br.bookPath = ''; br.bookUrl = ''; br.imageFormat = ''; br.archiveFormat = ''; {'page-progression'}) { echo "br.pageProgression = '" . $metaData->{"page-progression"} . "';\n"; } else { // Assume page progression is Left To Right echo "br.pageProgression = 'lr';\n"; } if ('browserlending' == $metaData->{'collection'}) { echo "br.olAuth = true;\n"; } else { echo "br.olAuth = false; //" . $metaData->{'collection'} ."\n"; } # Special cases if ('bandersnatchhsye00scarrich' == $id) { echo "br.mode = 2;\n"; echo "br.auto = true;\n"; } ?> // Check for config object // $$$ change this to use the newer params object if (typeof(brConfig) != 'undefined') { if (typeof(brConfig["ui"]) != 'undefined') { br.ui = brConfig["ui"]; } if (brConfig['mode'] == 1) { br.mode = 1; if (typeof(brConfig['reduce'] != 'undefined')) { br.reduce = brConfig['reduce']; } } else if (brConfig['mode'] == 2) { br.mode = 2; } } // brConfig function OLAuth() { //this.authUrl = 'http://home.us.archive.org/~rkumar/olauth.php?id=' + br.bookId; // XXXmang update to production this.authUrl = 'http://ol-mang:8080/ia_auth/' + br.bookId; //this.authUrl = 'http://openlibrary.org/ia_auth/' + br.bookId; return this; } OLAuth.prototype.init = function() { var htmlStr = '

Authenticating in-browser loan with openlibrary.org!

'; htmlStr += '

Please wait...

'; this.showPopup("#ddd", "#000", htmlStr); $.ajax({url:this.authUrl, dataType:'jsonp', jsonpCallback:'olAuth.initCallback'}); } OLAuth.prototype.showPopup = function(bgColor, textColor, msg) { this.popup = document.createElement("div"); $(this.popup).css({ position: 'absolute', top: '20px', left: ($('#BookReader').attr('clientWidth')-400)/2 + 'px', width: '400px', padding: "20px", border: "3px double #999999", zIndex: 3, backgroundColor: bgColor, color: textColor }).appendTo('#BookReader'); this.popup.innerHTML = msg; } OLAuth.prototype.initCallback = function(obj) { if (false == obj.success) { $(this.popup).css({ backgroundColor: "#f00", color: "#fff" }); this.popup.innerHTML = obj.msg; return; } //user is authenticated this.setCookie(obj.token); this.startPolling(); br.init(); } OLAuth.prototype.callback = function(obj) { if (false == obj.success) { this.showPopup("#f00", "#fff", obj.msg); clearInterval(this.poller); this.ttsPoller = null; } else { this.setCookie(obj.token); } } OLAuth.prototype.setCookie = function(value) { var date = new Date(); date.setTime(date.getTime()+(24*60*60*1000)); //one day expiry var expiry = date.toGMTString(); var cookie = 'loan-'+br.bookId+'='+value; cookie += '; expires='+expiry; cookie += '; path=/; domain=.archive.org;'; document.cookie = cookie; } OLAuth.prototype.startPolling = function () { var self = this; this.poller=setInterval(function(){ $.ajax({url:self.authUrl, dataType:'jsonp', jsonpCallback:'olAuth.callback'}); },300000); } br.cleanupMetadata(); if (br.olAuth) { var olAuth = new OLAuth(); olAuth.init(); } else { br.init(); } addToAccessFormats)) { if ("false" == strtolower(trim($page->addToAccessFormats))) { return false; } } return true; } // Returns { 'imageFormat' => , 'archiveFormat' => '} given a sub-item prefix and loaded xml data function findImageStack($subPrefix, $filesData) { // $$$ The order of the image formats determines which will be returned first $imageFormats = array('JP2' => 'jp2', 'TIFF' => 'tif', 'JPEG' => 'jpg'); $archiveFormats = array('ZIP' => 'zip', 'Tar' => 'tar'); $imageGroup = implode('|', array_keys($imageFormats)); $archiveGroup = implode('|', array_keys($archiveFormats)); // $$$ Currently only return processed images $imageStackRegex = "/Single Page (Processed) (${imageGroup}) (${archiveGroup})/"; foreach ($filesData->file as $file) { if (strpos($file['name'], $subPrefix) === 0) { // subprefix matches beginning if (preg_match($imageStackRegex, $file->format, $matches)) { // Make sure we have a regular image stack $imageFormat = $imageFormats[$matches[2]]; if (strpos($file['name'], $subPrefix . '_' . $imageFormat) === 0) { return array('imageFormat' => $imageFormat, 'archiveFormat' => $archiveFormats[$matches[3]], 'imageStackFile' => $file['name']); } } } } return array('imageFormat' => 'unknown', 'archiveFormat' => 'unknown', 'imageStackFile' => 'unknown'); } ?>