Add v0.0.3
This commit is contained in:
parent
f460bd8731
commit
2308af6033
19
CHANGELOG
19
CHANGELOG
|
@ -1,8 +1,17 @@
|
|||
0.0.3 - 20120507
|
||||
* Fixed many things blocking opensearch from working
|
||||
* There was a bug introduced in 0.0.2
|
||||
* The URL can't be relative for Mantano reader, so I added a configuration item.
|
||||
* I continued the refactoring to bring HTML to COPS
|
||||
* Thumbnails have bigger size (I'll add a configuration item later)
|
||||
* Add headers to help caching image and thumbnail to the browser
|
||||
*
|
||||
|
||||
0.0.2 - 20120411
|
||||
* Add support for MOBI and PDF
|
||||
* Major refactoring to prepare something nice for the future ;)
|
||||
* Add a config item to make use of X-Sendfile instead of X-Accel-Redirect
|
||||
if needed
|
||||
* Add support for MOBI and PDF
|
||||
* Major refactoring to prepare something nice for the future ;)
|
||||
* Add a config item to make use of X-Sendfile instead of X-Accel-Redirect if needed
|
||||
|
||||
0.0.1 - 20120302
|
||||
* First public release
|
||||
* First public release
|
||||
|
|
@ -11,6 +11,7 @@ require_once ("base.php");
|
|||
class OPDSRenderer
|
||||
{
|
||||
const PAGE_OPENSEARCH = "8";
|
||||
const PAGE_OPENSEARCH_QUERY = "9";
|
||||
|
||||
private $xmlStream = NULL;
|
||||
private $updated = NULL;
|
||||
|
@ -32,11 +33,13 @@ class OPDSRenderer
|
|||
}
|
||||
|
||||
public function getOpenSearch () {
|
||||
global $config;
|
||||
$xml = new XMLWriter ();
|
||||
$xml->openMemory ();
|
||||
$xml->setIndent (true);
|
||||
$xml->startDocument('1.0','UTF-8');
|
||||
$xml->startElement ("OpenSearchDescription");
|
||||
$xml->writeAttribute ("xmlns", "http://a9.com/-/spec/opensearch/1.1/");
|
||||
$xml->startElement ("ShortName");
|
||||
$xml->text ("My catalog");
|
||||
$xml->endElement ();
|
||||
|
@ -47,11 +50,18 @@ class OPDSRenderer
|
|||
$xml->text ("UTF-8");
|
||||
$xml->endElement ();
|
||||
$xml->startElement ("Image");
|
||||
$xml->writeAttribute ("type", "image/x-icon");
|
||||
$xml->writeAttribute ("width", "16");
|
||||
$xml->writeAttribute ("height", "16");
|
||||
$xml->text ("favicon.ico");
|
||||
$xml->endElement ();
|
||||
$xml->startElement ("Url");
|
||||
$xml->writeAttribute ("type", 'application/atom+xml');
|
||||
$xml->writeAttribute ("template", 'feed.php?page=' . self::PAGE_OPENSEARCH_QUERY . '&query={searchTerms}');
|
||||
$xml->writeAttribute ("template", $config['cops_full_url'] . 'feed.php?query={searchTerms}');
|
||||
$xml->endElement ();
|
||||
$xml->startElement ("Query");
|
||||
$xml->writeAttribute ("role", "example");
|
||||
$xml->writeAttribute ("searchTerms", "robot");
|
||||
$xml->endElement ();
|
||||
$xml->endElement ();
|
||||
$xml->endDocument();
|
||||
|
@ -89,9 +99,9 @@ class OPDSRenderer
|
|||
self::getXmlStream ()->text ("sebastien@slucas.fr");
|
||||
self::getXmlStream ()->endElement ();
|
||||
self::getXmlStream ()->endElement ();
|
||||
$link = new LinkNavigation ("feed.php", "start", "Home");
|
||||
$link = new LinkNavigation ("", "start", "Home");
|
||||
self::renderLink ($link);
|
||||
$link = new LinkNavigation ($_SERVER['REQUEST_URI'], "self");
|
||||
$link = new LinkNavigation ("?" . $_SERVER['QUERY_STRING'], "self");
|
||||
self::renderLink ($link);
|
||||
$link = new Link ("feed.php?page=" . self::PAGE_OPENSEARCH, "application/opensearchdescription+xml", "search", "Search here");
|
||||
self::renderLink ($link);
|
||||
|
@ -169,6 +179,18 @@ class OPDSRenderer
|
|||
|
||||
public function render ($page) {
|
||||
self::startXmlDocument ($page->title);
|
||||
if ($page->query)
|
||||
{
|
||||
self::getXmlStream ()->startElement ("opensearch:totalResults");
|
||||
self::getXmlStream ()->text (count($page->entryArray));
|
||||
self::getXmlStream ()->endElement ();
|
||||
self::getXmlStream ()->startElement ("opensearch:itemsPerPage");
|
||||
self::getXmlStream ()->text (count($page->entryArray));
|
||||
self::getXmlStream ()->endElement ();
|
||||
self::getXmlStream ()->startElement ("opensearch:startIndex");
|
||||
self::getXmlStream ()->text ("1");
|
||||
self::getXmlStream ()->endElement ();
|
||||
}
|
||||
foreach ($page->entryArray as $entry) {
|
||||
self::getXmlStream ()->startElement ("entry");
|
||||
self::renderEntry ($entry);
|
||||
|
@ -178,4 +200,4 @@ class OPDSRenderer
|
|||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
|
8
README
8
README
|
@ -74,6 +74,14 @@ If you choose to put your Calibre directory inside your web directory then you
|
|||
will have to edit /etc/nginx/mime.types to add this line :
|
||||
application/epub+zip epub;
|
||||
|
||||
= Notes on Opensearch =
|
||||
|
||||
Opensearch allow searching through an OPDS catalog. After many tests, I've been
|
||||
able to make it work with FBReader and Mantano Reader.
|
||||
|
||||
It seems that Aldiko didn't implement it properly so it won't work with COPS or
|
||||
any other custom OPDS catalog.
|
||||
|
||||
= Known problems =
|
||||
|
||||
* Only tested with Nginx.
|
||||
|
|
|
@ -21,7 +21,7 @@ class Author extends Base {
|
|||
}
|
||||
|
||||
public function getUri () {
|
||||
return "feed.php?page=".parent::PAGE_AUTHOR_DETAIL."&id=$this->id";
|
||||
return "?page=".parent::PAGE_AUTHOR_DETAIL."&id=$this->id";
|
||||
}
|
||||
|
||||
public function getEntryId () {
|
||||
|
@ -33,7 +33,7 @@ class Author extends Base {
|
|||
$nAuthors = parent::getDb ()->query('select count(*) from authors')->fetchColumn();
|
||||
$entry = new Entry ("Authors", self::ALL_AUTHORS_ID,
|
||||
"Alphabetical index of the $nAuthors authors", "text",
|
||||
array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_AUTHORS)));
|
||||
array ( new LinkNavigation ("?page=".parent::PAGE_ALL_AUTHORS)));
|
||||
return $entry;
|
||||
}
|
||||
|
||||
|
|
13
base.php
13
base.php
|
@ -26,6 +26,10 @@ class Link
|
|||
$this->rel = $prel;
|
||||
$this->title = $ptitle;
|
||||
}
|
||||
|
||||
public function hrefXhtml () {
|
||||
return str_replace ("&", "&", $this->href);
|
||||
}
|
||||
}
|
||||
|
||||
class LinkNavigation extends Link
|
||||
|
@ -34,6 +38,7 @@ class LinkNavigation extends Link
|
|||
|
||||
public function __construct($phref, $prel = NULL, $ptitle = NULL) {
|
||||
parent::__construct ($phref, self::OPDS_NAVIGATION_TYPE, $prel, $ptitle);
|
||||
$this->href = $_SERVER["SCRIPT_NAME"] . $this->href;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +81,14 @@ class EntryBook extends Entry
|
|||
$this->book = $pbook;
|
||||
$this->localUpdated = $pbook->timestamp;
|
||||
}
|
||||
|
||||
public function getCoverThumbnail () {
|
||||
foreach ($this->linkArray as $link) {
|
||||
if ($link->rel == "http://opds-spec.org/image/thumbnail")
|
||||
return $link->hrefXhtml ();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class Page
|
||||
|
|
42
book.php
42
book.php
|
@ -25,6 +25,7 @@ class Book extends Base {
|
|||
public $authors = NULL;
|
||||
public $serie = NULL;
|
||||
public $tags = NULL;
|
||||
public $format = array ();
|
||||
public static $mimetypes = array(
|
||||
'epub' => 'application/epub+zip',
|
||||
'mobi' => 'application/x-mobipocket-ebook',
|
||||
|
@ -59,6 +60,20 @@ class Book extends Base {
|
|||
return $this->authors;
|
||||
}
|
||||
|
||||
public function getAuthorsName () {
|
||||
$authorList = null;
|
||||
foreach ($this->getAuthors () as $author) {
|
||||
if ($authorList) {
|
||||
$authorList = $authorList . ", " . $author->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$authorList = $author->name;
|
||||
}
|
||||
}
|
||||
return $authorList;
|
||||
}
|
||||
|
||||
public function getSerie () {
|
||||
if (is_null ($this->serie)) {
|
||||
$this->serie = Serie::getSerieByBookId ($this->id);
|
||||
|
@ -84,6 +99,20 @@ class Book extends Base {
|
|||
return $this->tags;
|
||||
}
|
||||
|
||||
public function getTagsName () {
|
||||
$tagList = null;
|
||||
foreach ($this->getTags () as $tag) {
|
||||
if ($tagList) {
|
||||
$tagList = $tagList . ", " . $tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tagList = $tag;
|
||||
}
|
||||
}
|
||||
return $tagList;
|
||||
}
|
||||
|
||||
public function getComment () {
|
||||
$addition = "";
|
||||
$se = $this->getSerie ();
|
||||
|
@ -125,20 +154,21 @@ class Book extends Base {
|
|||
}
|
||||
else
|
||||
{
|
||||
array_push ($linkArray, new Link (rawurlencode ($this->path."/".$file), "image/jpeg", "http://opds-spec.org/image"));
|
||||
array_push ($linkArray, new Link (str_replace('%2F','/',rawurlencode ($this->path."/".$file)), "image/jpeg", "http://opds-spec.org/image"));
|
||||
}
|
||||
array_push ($linkArray, new Link ("fetch.php?id=$this->id&width=50", "image/jpeg", "http://opds-spec.org/image/thumbnail"));
|
||||
array_push ($linkArray, new Link ("fetch.php?id=$this->id&height=70", "image/jpeg", "http://opds-spec.org/image/thumbnail"));
|
||||
}
|
||||
foreach (self::$mimetypes as $ext => $mime)
|
||||
{
|
||||
if (preg_match ('/'. $ext .'$/', $file)) {
|
||||
$this->format [$ext] = $file;
|
||||
if (preg_match ('/^\//', $config['calibre_directory']))
|
||||
{
|
||||
array_push ($linkArray, new Link ("fetch.php?id=$this->id&type=" . $ext, $mime, "http://opds-spec.org/acquisition", "Download"));
|
||||
}
|
||||
else
|
||||
{
|
||||
array_push ($linkArray, new Link (rawurlencode ($this->path."/".$file), $mime, "http://opds-spec.org/acquisition", "Download"));
|
||||
array_push ($linkArray, new Link (str_replace('%2F','/',rawurlencode ($this->path."/".$file)), $mime, "http://opds-spec.org/acquisition", "Download"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,12 +201,12 @@ class Book extends Base {
|
|||
$entry = new Entry ("Books",
|
||||
self::ALL_BOOKS_ID,
|
||||
"Alphabetical index of the $nBooks books", "text",
|
||||
array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_BOOKS)));
|
||||
array ( new LinkNavigation ("?page=".parent::PAGE_ALL_BOOKS)));
|
||||
array_push ($result, $entry);
|
||||
$entry = new Entry ("Recents books",
|
||||
self::ALL_RECENT_BOOKS_ID,
|
||||
"Alphabetical index of the " . $config['cops_recentbooks_limit'] . " most recent books", "text",
|
||||
array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_RECENT_BOOKS)));
|
||||
array ( new LinkNavigation ("?page=".parent::PAGE_ALL_RECENT_BOOKS)));
|
||||
array_push ($result, $entry);
|
||||
return $result;
|
||||
}
|
||||
|
@ -253,7 +283,7 @@ order by substr (upper (sort), 1, 1)");
|
|||
{
|
||||
array_push ($entryArray, new Entry ($post->title, "allbooks_" . $post->title,
|
||||
"$post->count books", "text",
|
||||
array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_BOOKS_LETTER."&id=".$post->title))));
|
||||
array ( new LinkNavigation ("?page=".parent::PAGE_ALL_BOOKS_LETTER."&id=".$post->title))));
|
||||
}
|
||||
return $entryArray;
|
||||
}
|
||||
|
|
|
@ -6,13 +6,15 @@
|
|||
* @author Sébastien Lucas <sebastien@slucas.fr>
|
||||
*/
|
||||
|
||||
$config = array();
|
||||
if (!isset($config))
|
||||
$config = array();
|
||||
|
||||
/*
|
||||
* The directory containing calibre's metadata.db file, with sub-directories
|
||||
* containing all the formats.
|
||||
* If this directory starts with a / EPUB download will only work with Nginx
|
||||
* and if the calibre_internal_directory is set
|
||||
* and the calibre_internal_directory has to be set properly
|
||||
* BEWARE : it has to end with a /
|
||||
*/
|
||||
$config['calibre_directory'] = './';
|
||||
|
||||
|
@ -23,7 +25,14 @@
|
|||
$config['calibre_internal_directory'] = '/Calibre/';
|
||||
|
||||
/*
|
||||
* Number of books
|
||||
* Full URL prefix (with trailing /)
|
||||
* usefull especially for Opensearch where a full URL is sometimes required
|
||||
* For example Mantano requires it.
|
||||
*/
|
||||
$config['cops_full_url'] = '';
|
||||
|
||||
/*
|
||||
* Number of recent books to show
|
||||
*/
|
||||
$config['cops_recentbooks_limit'] = '50';
|
||||
|
||||
|
@ -39,5 +48,5 @@
|
|||
* X-Accel-Redirect : For Nginx
|
||||
* X-Sendfile : For Lightttpd or Apache (with mod_xsendfile)
|
||||
*/
|
||||
$config['cops_x_accel_redirect'] = "X-Accel-Redirect";
|
||||
$config['cops_x_accel_redirect'] = "X-Accel-Redirect";
|
||||
?>
|
2
feed.php
2
feed.php
|
@ -17,6 +17,8 @@
|
|||
header ("Content-Type:application/xml");
|
||||
$page = getURLParam ("page", Base::PAGE_INDEX);
|
||||
$query = getURLParam ("query");
|
||||
if ($query)
|
||||
$page = Base::PAGE_OPENSEARCH_QUERY;
|
||||
$qid = getURLParam ("id");
|
||||
|
||||
$OPDSRender = new OPDSRenderer ();
|
||||
|
|
29
fetch.php
29
fetch.php
|
@ -10,6 +10,10 @@
|
|||
require_once ("book.php");
|
||||
|
||||
global $config;
|
||||
$expires = 60*60*24*14;
|
||||
header("Pragma: public");
|
||||
header("Cache-Control: maxage=".$expires);
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');
|
||||
$bookId = $_GET["id"];
|
||||
$book = Book::getBookById($bookId);
|
||||
$type = getURLParam ("type", "jpg");
|
||||
|
@ -43,6 +47,31 @@
|
|||
imagedestroy($dst_img);
|
||||
return;
|
||||
}
|
||||
if (isset($_GET["height"]))
|
||||
{
|
||||
$file = $book->getFilePath ($type);
|
||||
// get image size
|
||||
if($size = GetImageSize($file)){
|
||||
$w = $size[0];
|
||||
$h = $size[1];
|
||||
//set new size
|
||||
$nh = $_GET["height"];
|
||||
$nw = ($nh*$w)/$h;
|
||||
}
|
||||
else{
|
||||
//set new size
|
||||
$nw = "160";
|
||||
$nh = "120";
|
||||
}
|
||||
//draw the image
|
||||
$src_img = imagecreatefromjpeg($file);
|
||||
$dst_img = imagecreatetruecolor($nw,$nh);
|
||||
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nw, $nh, $w, $h);//resizing the image
|
||||
imagejpeg($dst_img,"",100);
|
||||
imagedestroy($src_img);
|
||||
imagedestroy($dst_img);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
header("Content-type: " . Book::$mimetypes[$type]);
|
||||
|
|
|
@ -20,14 +20,14 @@ class Serie extends Base {
|
|||
}
|
||||
|
||||
public function getUri () {
|
||||
return "feed.php?page=".parent::PAGE_SERIE_DETAIL."&id=$this->id";
|
||||
return "?page=".parent::PAGE_SERIE_DETAIL."&id=$this->id";
|
||||
}
|
||||
|
||||
public static function getCount() {
|
||||
$nSeries = parent::getDb ()->query('select count(*) from series')->fetchColumn();
|
||||
$entry = new Entry ("Series", self::ALL_SERIES_ID,
|
||||
"Alphabetical index of the $nSeries series", "text",
|
||||
array ( new LinkNavigation ("feed.php?page=".parent::PAGE_ALL_SERIES)));
|
||||
array ( new LinkNavigation ("?page=".parent::PAGE_ALL_SERIES)));
|
||||
return $entry;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ order by series.sort');
|
|||
{
|
||||
array_push ($entryArray, new Entry ($post->sort, self::ALL_SERIES_ID.":".$post->id,
|
||||
"$post->count books", "text",
|
||||
array ( new LinkNavigation ("feed.php?page=".parent::PAGE_SERIE_DETAIL."&id=$post->id"))));
|
||||
array ( new LinkNavigation ("?page=".parent::PAGE_SERIE_DETAIL."&id=$post->id"))));
|
||||
}
|
||||
return $entryArray;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue