Location: PHPKode > projects > VuFind > vufind-1.0.1/web/bookcover.php
<?php
/**
 *
 * Copyright (C) Villanova University 2007.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/*
 * @todo    Convert this to an AJAX approach to allow for client side access to
 *          images.  Also investigate local caching approach.  What about using
 *          Squid?
 */

require_once 'sys/Proxy_Request.php';

// Retrieve values from configuration file
$configArray = parse_ini_file('conf/config.ini', true);

// Proxy server settings
if (isset($configArray['Proxy']['host'])) {
  if (isset($configArray['Proxy']['port'])) {
    $proxy_server = $configArray['Proxy']['host'].":".$configArray['Proxy']['port'];
  } else {
    $proxy_server = $configArray['Proxy']['host'];
  }
  $proxy = array('http' => array('proxy' => "tcp://$proxy_server", 'request_fulluri' => true));
  stream_context_get_default($proxy);
}

if (!count($_GET)) {
    dieWithFailImage();
}

// Sanitize incoming parameters to avoid filesystem attacks.  We'll make sure the
// provided size matches a whitelist, and we'll strip illegal characters from the
// ISBN.
$validSizes = array('small', 'medium', 'large');
if (!in_array($_GET['size'], $validSizes)) {
    dieWithFailImage();
}
$_GET['isn'] = preg_replace('/[^0-9xX]/', '', $_GET['isn']);

// Do we have a non-empty ISBN?
if (isset($_GET['isn']) && !empty($_GET['isn'])) {
    $localFile = 'images/covers/' . $_GET['size'] . '/' . $_GET['isn'] . '.jpg';
    if (is_readable($localFile)) {
        // Load local cache if available
        header('Content-type: image/jpeg');
        echo readfile($localFile);
    } else {
        // Fetch from provider
        if (isset($configArray['Content']['coverimages'])) {
            $providers = explode(',', $configArray['Content']['coverimages']);
            $success = 0;
            foreach ($providers as $provider) {
                $provider = explode(':', $provider);
                $func = $provider[0];
                $key = $provider[1];
                if ($func($key)) {
                    $success = 1;
                    break;
                }
            }
            if (!$success) {
                dieWithFailImage();
            }
        } else {
            dieWithFailImage();
        }
    }
} else {
    dieWithFailImage();
}

/**
 * Display a "cover unavailable" graphic and terminate execution.
 */
function dieWithFailImage()
{
    header('Content-type: image/gif');
    echo readfile('images/noCover2.gif');
    exit();
}

/**
 * Load image from URL, store in cache if requested, display if possible.
 *
 * @param   $url        URL to load image from
 * @param   $cache      Boolean -- should we store in local cache?
 * @return  bool        True if image displayed, false on failure.
 */
function processImageURL($url, $cache = true)
{
    global $localFile;
    
    if ($image = @file_get_contents($url)) {
        // Figure out file paths -- $tempFile will be used to store the downloaded
        // image for analysis.  $finalFile will be used for long-term storage if
        // $cache is true or for temporary display purposes if $cache is false.
        $tempFile = str_replace('.jpg', uniqid(), $localFile);
        $finalFile = $cache ? $localFile : $tempFile . '.jpg';
        
        // If some services can't provide an image, they will serve a 1x1 blank
        // or give us invalid image data.  Let's analyze what came back before
        // proceeding.
        if (!@file_put_contents($tempFile, $image)) {
            die("Unable to write to image directory.");
        }
        list($width, $height, $type) = @getimagesize($tempFile);
        
        // File too small -- delete it and report failure.
        if ($width < 2 && $height < 2) {
            @unlink($tempFile);
            return false;
        }
        
        // Conversion needed -- do some normalization for non-JPEG images:
        if ($type != IMAGETYPE_JPEG) {
            // We no longer need the temp file:
            @unlink($tempFile);
            
            // Try to create a GD image and rewrite as JPEG, fail if we can't:
            if (!($imageGD = @imagecreatefromstring($image))) {
                return false;
            }
            if (!@imagejpeg($imageGD, $finalFile)) {
                return false;
            }
        } else {
            // If $tempFile is already a JPEG, let's store it in the cache.
            @rename($tempFile, $finalFile);
        }
        
        // Display the image:
        header('Content-type: image/jpeg');
        readfile($finalFile);
        
        // If we don't want to cache the image, delete it now that we're done.
        if (!$cache) {
            @unlink($finalFile);
        }
        
        return true;
    } else {
        return false;
    }
}

function syndetics($id)
{
    global $configArray;

    switch ($_GET['size']) {
        case 'small':
            $size = 'SC.GIF';
            break;
        case 'medium':
            $size = 'MC.GIF';
            break;
        case 'large':
            $size = 'LC.JPG';
            break;
    }

    $url = isset($configArray['Syndetics']['url']) ? 
            $configArray['Syndetics']['url'] : 'http://syndetics.com';
    $url .= "/index.aspx?type=xw12&isbn={$_GET['isn']}/{$size}&client={$id}";
    return processImageURL($url);
}

function librarything($id)
{
    $url = 'http://covers.librarything.com/devkey/' . $id . '/' . $_GET['size'] . '/isbn/' . $_GET['isn'];
    return processImageURL($url);
}

function openlibrary()
{
    // Convert internal size value to openlibrary equivalent:
    switch($_GET['size']) {
        case 'large':
            $size = 'L';
            break;
        case 'medium': 
            $size = 'M';
            break;
        case 'small':
        default:
            $size = 'S';
            break;
    }
    
    // Retrieve the image; the default=false parameter indicates that we want a 404
    // if the ISBN is not supported.
    $url = "http://covers.openlibrary.org/b/isbn/{$_GET['isn']}-{$size}.jpg?default=false";
    return processImageURL($url);
}

function google()
{
    if (is_callable('json_decode')) {
        $url = 'http://books.google.com/books?jscmd=viewapi&' .
               'bibkeys=ISBN:' . $_GET['isn'] . '&callback=addTheCover';
        $client = new Proxy_Request();
        $client->setMethod(HTTP_REQUEST_METHOD_GET);
        $client->setURL($url);

        $result = $client->sendRequest();
        if (!PEAR::isError($result)) {
            $json = $client->getResponseBody();

            // strip off addthecover( -- note that we need to account for length of ISBN (10 or 13)
            $json = substr($json, 21 + strlen($_GET['isn']));
            // strip off );
            $json = substr($json, 0, -3);
            // convert \x26 to &
            $json = str_replace("\\x26", "&", $json);
            if ($json = json_decode($json, true)) {
                return processImageURL($json['thumbnail_url'], false);
            }
        }
    }
    return false;
}

function amazon($id)
{
    require_once 'sys/Amazon.php';
    require_once 'XML/Unserializer.php';

    $params = array('ResponseGroup' => 'Images', 'ItemId' => $_GET['isn']);
    $request = new AWS_Request($id, 'ItemLookup', $params);
    $result = $request->sendRequest();
    if (!PEAR::isError($result)) {
        $unxml = new XML_Unserializer();
        $unxml->unserialize($result);
        $data = $unxml->getUnserializedData();
        if (PEAR::isError($data)) {
            return false;
        }
        if (!$data['Items']['Item']['ASIN']) {
            $data['Items']['Item'] = $data['Items']['Item'][0];
        }
        if (isset($data['Items']['Item'])) {
            // Where in the XML can we find the URL we need?
            switch ($_GET['size']) {
                case 'small':
                    $imageIndex = 'SmallImage';
                    break;
                case 'medium':
                    $imageIndex = 'MediumImage';
                    break;
                case 'large':
                    $imageIndex = 'LargeImage';
                    break;
                default:
                    $imageIndex = false;
                    break;
            }
            
            // Does a URL exist?
            if ($imageIndex && isset($data['Items']['Item'][$imageIndex]['URL'])) {
                $imageUrl = $data['Items']['Item'][$imageIndex]['URL'];
                return processImageURL($imageUrl, false);
            }
        }
    }

    return false;
}
?>
Return current item: VuFind