Make dragscrollable update when there is a new version
[bookreader.git] / BookReaderIA / datanode / BookReaderMeta.inc.php
index ce77e62..fcd1803 100644 (file)
@@ -26,15 +26,31 @@ This file is part of BookReader.
 
 class BookReaderMeta {
 
+    // Fields from _meta.xml to add to response (if present)
+    var $metaFields = array(
+        'title' => 'title',
+        'author' => 'author',
+        'publisher' => 'publisher',
+        'date' => 'date',
+        'language' => 'language',
+        'contributor' => 'contributor',
+        'collection' => 'collection',
+        'page-progression' => 'pageProgression',
+    );
+    
+    var $metaDefaults = array(
+        'pageProgression' => 'lr',
+    );
+
     // Builds metadata object (to be encoded as JSON)
     function buildMetadata($id, $itemPath, $bookId, $server) {
     
         $response = array();
         
-        if (! $subPrefix) {
-            $subPrefix = $id;
+        if (! $bookId) {
+            $bookId = $id;
         }
-        $subItemPath = $itemPath . '/' . $subPrefix;
+        $subItemPath = $itemPath . '/' . $bookId;
         
         if ("" == $id) {
             $this->BRFatal("No identifier specified!");
@@ -62,7 +78,7 @@ class BookReaderMeta {
             $this->BRfatal("File metadata not found!");
         }
         
-        $imageStackInfo = $this->findImageStack($subPrefix, $filesData);
+        $imageStackInfo = $this->findImageStack($bookId, $filesData);
         if ($imageStackInfo['imageFormat'] == 'unknown') {
             $this->BRfatal('Couldn\'t find image stack');
         }
@@ -83,8 +99,10 @@ class BookReaderMeta {
         $scanDataFile = "${subItemPath}_scandata.xml";
         $scanDataZip  = "$itemPath/scandata.zip";
         if (file_exists($scanDataFile)) {
+            $this->checkPrivs($scanDataFile);
             $scanData = simplexml_load_file($scanDataFile);
         } else if (file_exists($scanDataZip)) {
+            $this->checkPrivs($scanDataZip);
             $cmd  = 'unzip -p ' . escapeshellarg($scanDataZip) . ' scandata.xml';
             exec($cmd, $output, $retval);
             if ($retval != 0) {
@@ -143,39 +161,44 @@ class BookReaderMeta {
         }
                 
         # Load some values from meta.xml
-        $pageProgression = 'lr'; // default
-        if ('' != $metaData->{'page-progression'}) {
-          $pageProgression = $metaData->{"page-progression"};
+        foreach ($this->metaFields as $srcName => $destName) {
+            if ($metaData->{$srcName}) {
+                $response[$destName] = $metaData->{$srcName} . '';
+            } else {
+                if (array_key_exists($destName, $this->metaDefaults)) {
+                    $response[$destName] = $this->metaDefaults[$destName];
+                }
+            }
         }
         
         // General metadata
-        $response['title'] = $metaData->title . ''; // XXX renamed
-        $response['numPages'] = count($pageNums); // XXX renamed    
+        $response['numPages'] = count($pageNums); // $$$ renamed    
         if ('' != $titleLeaf) {
-            $response['titleLeaf'] = $titleLeaf; // XXX change to titleIndex - do leaf mapping here
+            $response['titleLeaf'] = $titleLeaf; // $$$ change to titleIndex - do leaf mapping here
             $titleIndex = $this->indexForLeaf($titleLeaf, $leafNums);
             if ($titleIndex !== NULL) {
                 $response['titleIndex'] = intval($titleIndex);
             }
         }
         $response['url'] = "http://www.archive.org/details/$id";
-        $response['pageProgression'] = $pageProgression . '';
         $response['pageWidths'] = $pageWidths;
         $response['pageHeights'] = $pageHeights;
         $response['pageNums'] = $pageNums;
         
         // Internet Archive specific
-        $response['itemId'] = $id; // XXX renamed
-        $response['bookId'] = $subPrefix;  // XXX renamed
+        $response['itemId'] = $id; // $$$ renamed
+        $response['bookId'] = $bookId;  // $$$ renamed
+        $response['itemPath'] = $itemPath;
         $response['zip'] = $imageStackFile;
         $response['server'] = $server;
         $response['imageFormat'] = $imageFormat;
         $response['archiveFormat'] = $archiveFormat;
         $response['leafNums'] = $leafNums;
+        $response['previewImage'] = $this->previewURL('preview', $response);
         
         // URL to title image
         if ('' != $titleLeaf) {
-            $response['titleImage'] = $this->imageURL($titleLeaf, $response);
+            $response['titleImage'] = $this->previewURL('title', $response);
         }
         
         if (count($coverLeafs) > 0) {
@@ -183,26 +206,14 @@ class BookReaderMeta {
             $coverImages = array();
             foreach ($coverLeafs as $key => $leafNum) {
                 array_push($coverIndices, $this->indexForLeaf($leafNum, $leafNums));
+                // $$$ TODO use preview API once it supports multiple covers
                 array_push($coverImages, $this->imageUrl($leafNum, $response));
             }
             
             $response['coverIndices'] = $coverIndices;
             $response['coverImages'] = $coverImages;
         }
-        
-        // Determine "preview" image, which may be the cover, title, or first page
-        if (array_key_exists('titleImage', $response)) {
-            // Use title image if was assert
-            $previewImage = $response['titleImage'];
-        } else if (array_key_exists('coverImages', $response)) {
-            // Try for the cover page
-            $previewImage = $response['coverImages'][0];
-        } else {
-            // Neither title nor cover asserted, use first page
-            $previewImage = $this->imageURL(0, $response);
-        }
-        $response['previewImage'] = $previewImage;
-        
+                
         return $response;
     }
     
@@ -231,8 +242,9 @@ class BookReaderMeta {
     
     function BRFatal($string) {
         // $$$ TODO log error
-        echo "alert('$string');\n";
-        die(-1);
+        throw new Exception("Metadata error: $string");
+        //echo "alert('$string');\n";
+        //die(-1);
     }
     
     // Returns true if a page should be added based on it's information in
@@ -292,7 +304,11 @@ class BookReaderMeta {
         }
     }
     
-    function imageURL($leafNum, $metadata, $scale, $rotate) {
+    function leafForIndex($index, $leafNums) {
+        return $leafNums[$index]; // $$$ todo change to instance variables
+    }
+    
+    function imageURL($leafNum, $metadata, $scale = null, $rotate = null) {
         // "Under the hood", non-public, dynamically changing (achtung!) image URLs currently look like:
         // http://{server}/BookReader/BookReaderImages.php?zip={zipPath}&file={filePath}&scale={scale}&rotate={rotate}
         // e.g. http://ia311213.us.archive.org/BookReader/BookReaderImages.php?zip=/0/items/coloritsapplicat00andriala/coloritsapplicat00andriala_jp2.zip&file=coloritsapplicat00andriala_jp2/coloritsapplicat00andriala_0009.jp2&scale=8&rotate=0
@@ -301,24 +317,46 @@ class BookReaderMeta {
         $filePath = $this->imageFilePath($leafNum, $metadata['bookId'], $metadata['imageFormat']);
         $url = 'http://' . $metadata['server'] . '/BookReader/BookReaderImages.php?zip=' . $metadata['zip'] . '&file=' . $filePath;
         
-        if (defined($scale)) {
+        if ($scale !== null) {
             $url .= '&scale=' . $scale;
         }
-        if (defined($rotate)) {
+        if ($rotate !== null) {
             $url .= '&rotate=' . $rotate;
         }
         
         return $url;
     }
     
+    // $$$ move inside BookReaderPreview
+    function previewURL($page, $metadata) {
+        $query = array(
+            'id' => $metadata['itemId'],
+            'bookId' => $metadata['bookId'],
+            'itemPath' => $metadata['itemPath'],
+            'server' => $metadata['server'],
+            'page' => $page,
+        );
+        
+        return 'http://' . $metadata['server'] . '/BookReader/BookReaderPreview.php?' . http_build_query($query, '', '&');
+    }
+    
     function imageFilePath($leafNum, $bookId, $format) {
         return sprintf("%s_%s/%s_%04d.%s", $bookId, $format, $bookId, intval($leafNum), $format);
     }
     
+    // Parse date from _meta.xml to integer
+    function parseYear($dateFromMetaXML) {
+        // grab the first run of digits
+        if (preg_match('|(\d+)|', $dateFromMetaXML, $matches)) {
+            return (int)$matches[1];
+        }
+        return null;
+    }
+    
     function processRequest($requestEnv) {
-        $id = $requestEnv['itemId']; // XXX renamed
+        $id = $requestEnv['itemId']; // $$$ renamed
         $itemPath = $requestEnv['itemPath'];
-        $bookId = $requestEnv['bookId']; // XXX renamed
+        $bookId = $requestEnv['bookId']; // $$$ renamed
         $server = $requestEnv['server'];
         
         // Check if we're on a dev vhost and point to JSIA in the user's public_html on the datanode
@@ -331,6 +369,14 @@ class BookReaderMeta {
         
         $this->emitResponse( $this->buildMetadata($id, $itemPath, $bookId, $server) );
     }
+    
+    function checkPrivs($filename) {
+        if (!is_readable($filename)) {
+            header('HTTP/1.1 403 Forbidden');
+            exit(0);
+        }
+    }
+
 }
 
 ?>