mirror of
https://github.com/standardebooks/web.git
synced 2025-07-14 02:21:55 -04:00
Add thank-you page to ebook downloads
This commit is contained in:
parent
29fc6f9ff2
commit
9437beaee9
9 changed files with 222 additions and 16 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,5 @@
|
||||||
ebooks/*
|
ebooks/*
|
||||||
www/ebooks/*
|
www/ebooks/*/
|
||||||
www/images/covers/*
|
www/images/covers/*
|
||||||
www/feeds/opds/*.xml
|
www/feeds/opds/*.xml
|
||||||
www/feeds/opds/*/*.xml
|
www/feeds/opds/*/*.xml
|
||||||
|
|
|
@ -218,6 +218,9 @@ Define webroot /standardebooks.org/web
|
||||||
# Redirect latest version of the manual
|
# Redirect latest version of the manual
|
||||||
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
|
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
|
||||||
|
|
||||||
|
# Rewrite ebook downloads
|
||||||
|
RewriteRule ^/ebooks/(.+?)/download$ /ebooks/download.php?url-path=$1 [QSA]
|
||||||
|
|
||||||
# List of specific URL rewrites
|
# List of specific URL rewrites
|
||||||
RewriteRule ^/contribute/accepted-ebooks/? /contribute/collections-policy [R=301,L]
|
RewriteRule ^/contribute/accepted-ebooks/? /contribute/collections-policy [R=301,L]
|
||||||
RewriteRule ^/ebooks/aristotle/the-nicomachean-ethics(/?$|/.+?$) /ebooks/aristotle/nicomachean-ethics$1 [R=301,L]
|
RewriteRule ^/ebooks/aristotle/the-nicomachean-ethics(/?$|/.+?$) /ebooks/aristotle/nicomachean-ethics$1 [R=301,L]
|
||||||
|
@ -307,18 +310,25 @@ Define webroot /standardebooks.org/web
|
||||||
|
|
||||||
RewriteRule ^/artworks/([^/\.]+)/([^/\.]+)/edit$ /artworks/edit.php?artist-url-name=$1&artwork-url-name=$2 [L]
|
RewriteRule ^/artworks/([^/\.]+)/([^/\.]+)/edit$ /artworks/edit.php?artist-url-name=$1&artwork-url-name=$2 [L]
|
||||||
|
|
||||||
# Specific config for /bulk-downloads
|
# Specific config for /ebooks/<author>/<ebook>/downloads
|
||||||
<DirectoryMatch "${webroot}/www/bulk-downloads">
|
<DirectoryMatch "^${webroot}/www/ebooks/.+">
|
||||||
# Both directives are required
|
# Both directives are required
|
||||||
XSendFile on
|
XSendFile on
|
||||||
XSendFilePath /standardebooks.org/web/www/bulk-downloads
|
XSendFilePath ${webroot}/www/ebooks
|
||||||
|
</DirectoryMatch>
|
||||||
|
|
||||||
|
# Specific config for /bulk-downloads
|
||||||
|
<DirectoryMatch "^${webroot}/www/bulk-downloads/">
|
||||||
|
# Both directives are required
|
||||||
|
XSendFile on
|
||||||
|
XSendFilePath ${webroot}/www/bulk-downloads
|
||||||
</DirectoryMatch>
|
</DirectoryMatch>
|
||||||
|
|
||||||
# Specific config for /feeds
|
# Specific config for /feeds
|
||||||
<DirectoryMatch "^${webroot}/www/feeds">
|
<DirectoryMatch "^${webroot}/www/feeds/">
|
||||||
# This must be defined at the top level /feeds/ directory
|
# This must be defined at the top level /feeds/ directory
|
||||||
# Both directives are required
|
# Both directives are required
|
||||||
XSendFile on
|
XSendFile on
|
||||||
XSendFilePath /standardebooks.org/web/www/feeds
|
XSendFilePath ${webroot}/www/feeds
|
||||||
</DirectoryMatch>
|
</DirectoryMatch>
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
|
@ -200,6 +200,9 @@ Define webroot /standardebooks.org/web
|
||||||
# Redirect latest version of the manual
|
# Redirect latest version of the manual
|
||||||
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
|
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
|
||||||
|
|
||||||
|
# Rewrite ebook downloads
|
||||||
|
RewriteRule ^/ebooks/(.+?)/download$ /ebooks/download.php?url-path=$1 [QSA]
|
||||||
|
|
||||||
# List of specific URL rewrites
|
# List of specific URL rewrites
|
||||||
RewriteRule ^/contribute/accepted-ebooks/? /contribute/collections-policy [R=301,L]
|
RewriteRule ^/contribute/accepted-ebooks/? /contribute/collections-policy [R=301,L]
|
||||||
RewriteRule ^/ebooks/aristotle/the-nicomachean-ethics(/?$|/.+?$) /ebooks/aristotle/nicomachean-ethics$1 [R=301,L]
|
RewriteRule ^/ebooks/aristotle/the-nicomachean-ethics(/?$|/.+?$) /ebooks/aristotle/nicomachean-ethics$1 [R=301,L]
|
||||||
|
@ -289,18 +292,25 @@ Define webroot /standardebooks.org/web
|
||||||
|
|
||||||
RewriteRule ^/artworks/([^/\.]+)/([^/\.]+)/edit$ /artworks/edit.php?artist-url-name=$1&artwork-url-name=$2 [L]
|
RewriteRule ^/artworks/([^/\.]+)/([^/\.]+)/edit$ /artworks/edit.php?artist-url-name=$1&artwork-url-name=$2 [L]
|
||||||
|
|
||||||
# Specific config for /bulk-downloads
|
# Specific config for /ebooks/<author>/<ebook>/downloads
|
||||||
<DirectoryMatch "${webroot}/www/bulk-downloads">
|
<DirectoryMatch "^${webroot}/www/ebooks/.+">
|
||||||
# Both directives are required
|
# Both directives are required
|
||||||
XSendFile on
|
XSendFile on
|
||||||
XSendFilePath /standardebooks.org/web/www/bulk-downloads
|
XSendFilePath ${webroot}/www/ebooks
|
||||||
|
</DirectoryMatch>
|
||||||
|
|
||||||
|
# Specific config for /bulk-downloads
|
||||||
|
<DirectoryMatch "^${webroot}/www/bulk-downloads/">
|
||||||
|
# Both directives are required
|
||||||
|
XSendFile on
|
||||||
|
XSendFilePath ${webroot}/www/bulk-downloads
|
||||||
</DirectoryMatch>
|
</DirectoryMatch>
|
||||||
|
|
||||||
# Specific config for /feeds
|
# Specific config for /feeds
|
||||||
<DirectoryMatch "^${webroot}/www/feeds">
|
<DirectoryMatch "^${webroot}/www/feeds/">
|
||||||
# This must be defined at the top level /feeds/ directory
|
# This must be defined at the top level /feeds/ directory
|
||||||
# Both directives are required
|
# Both directives are required
|
||||||
XSendFile on
|
XSendFile on
|
||||||
XSendFilePath /standardebooks.org/web/www/feeds
|
XSendFilePath ${webroot}/www/feeds
|
||||||
</DirectoryMatch>
|
</DirectoryMatch>
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
15
lib/EbookFormat.php
Normal file
15
lib/EbookFormat.php
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?
|
||||||
|
|
||||||
|
enum EbookFormat: string{
|
||||||
|
case Epub = 'epub';
|
||||||
|
case Azw3 = 'azw3';
|
||||||
|
case Kepub = 'kepub';
|
||||||
|
case AdvancedEpub = 'advanced-epub';
|
||||||
|
|
||||||
|
public function GetMimeType(): string{
|
||||||
|
return match($this){
|
||||||
|
self::Azw3 => 'application/x-mobi8-ebook',
|
||||||
|
default => 'application/epub+zip'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ $isXslt = $isXslt ?? false;
|
||||||
$feedUrl = $feedUrl ?? null;
|
$feedUrl = $feedUrl ?? null;
|
||||||
$feedTitle = $feedTitle ?? '';
|
$feedTitle = $feedTitle ?? '';
|
||||||
$isErrorPage = $isErrorPage ?? false;
|
$isErrorPage = $isErrorPage ?? false;
|
||||||
|
$downloadUrl = $downloadUrl ?? null;
|
||||||
|
|
||||||
// As of Sep 2022, all versions of Safari have a bug where if the page is served as XHTML,
|
// As of Sep 2022, all versions of Safari have a bug where if the page is served as XHTML,
|
||||||
// then <picture> elements download all <source>s instead of the first supported match.
|
// then <picture> elements download all <source>s instead of the first supported match.
|
||||||
|
@ -81,6 +82,9 @@ if(!$isXslt){
|
||||||
<meta content="@standardebooks" name="twitter:site"/>
|
<meta content="@standardebooks" name="twitter:site"/>
|
||||||
<meta content="@standardebooks" name="twitter:creator"/>
|
<meta content="@standardebooks" name="twitter:creator"/>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
<? if($downloadUrl !== null){ ?>
|
||||||
|
<meta http-equiv="refresh" content="0; url=<?= Formatter::EscapeHtml($downloadUrl) ?>" />
|
||||||
|
<? } ?>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
|
|
@ -1490,7 +1490,8 @@ ol.ebooks-list > li p{
|
||||||
hyphens: none;
|
hyphens: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
ol.ebooks-list > li img{
|
ol.ebooks-list > li img,
|
||||||
|
img.ebook{
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
@ -2905,6 +2906,21 @@ ul.feed p{
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stinger{
|
||||||
|
font-family: "Crimson Pro", serif;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thank-you-container{
|
||||||
|
display: flex;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thank-you-container picture{
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media (hover: none) and (pointer: coarse){ /* target ipads and smartphones without a mouse */
|
@media (hover: none) and (pointer: coarse){ /* target ipads and smartphones without a mouse */
|
||||||
/* For iPad, unset the height so it matches the other elements */
|
/* For iPad, unset the height so it matches the other elements */
|
||||||
select[multiple]{
|
select[multiple]{
|
||||||
|
@ -3157,6 +3173,12 @@ ul.feed p{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media(max-width: 860px){
|
||||||
|
.thank-you-container picture{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media(max-width: 730px){
|
@media(max-width: 730px){
|
||||||
form[action="/ebooks"]{
|
form[action="/ebooks"]{
|
||||||
grid-template-columns: auto auto 1fr 1fr;
|
grid-template-columns: auto auto 1fr 1fr;
|
||||||
|
|
127
www/ebooks/download.php
Normal file
127
www/ebooks/download.php
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
<?
|
||||||
|
use function Safe\apcu_fetch;
|
||||||
|
|
||||||
|
// If the user is not logged in, or has less than some amount of downloads, show a thank-you page
|
||||||
|
|
||||||
|
$ebook = null;
|
||||||
|
$downloadCount = $_COOKIE['download-count'] ?? 0;
|
||||||
|
$showThankYouPage = $GLOBALS['User'] === null && $downloadCount < 5;
|
||||||
|
$downloadUrl = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
$urlPath = HttpInput::Str(GET, 'url-path') ?? null;
|
||||||
|
$format = EbookFormat::tryFrom(HttpInput::Str(GET, 'format') ?? '') ?? EbookFormat::Epub;
|
||||||
|
$wwwFilesystemPath = EBOOKS_DIST_PATH . $urlPath;
|
||||||
|
|
||||||
|
// Do we have the ebook cached?
|
||||||
|
try{
|
||||||
|
$ebook = apcu_fetch('ebook-' . $wwwFilesystemPath);
|
||||||
|
}
|
||||||
|
catch(Safe\Exceptions\ApcuException){
|
||||||
|
$ebook = new Ebook($wwwFilesystemPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($ebook === null){
|
||||||
|
throw new Exceptions\InvalidFileException();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($format){
|
||||||
|
case EbookFormat::Kepub:
|
||||||
|
$downloadUrl = $ebook->KepubUrl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EbookFormat::Azw3:
|
||||||
|
$downloadUrl = $ebook->Azw3Url;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EbookFormat::AdvancedEpub:
|
||||||
|
$downloadUrl = $ebook->AdvancedEpubUrl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EbookFormat::Epub:
|
||||||
|
default:
|
||||||
|
$downloadUrl = $ebook->EpubUrl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$showThankYouPage){
|
||||||
|
// Download the file directly, without showing the thank you page
|
||||||
|
$downloadPath = WEB_ROOT . $downloadUrl;
|
||||||
|
|
||||||
|
if(!is_file($downloadPath)){
|
||||||
|
throw new Exceptions\InvalidFileException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything OK, serve the file using Apache.
|
||||||
|
// The xsendfile Apache module tells Apache to serve the file, including not-modified or etag headers.
|
||||||
|
// Much more efficient than reading it in PHP and outputting it that way.
|
||||||
|
header('X-Sendfile: ' . $downloadPath);
|
||||||
|
header('Content-Type: ' . $format->GetMimeType());
|
||||||
|
header('Content-Disposition: attachment; filename="' . basename($downloadPath) . '"');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment local download count, expires in 2 weeks
|
||||||
|
$downloadCount++;
|
||||||
|
setcookie('download-count', (string)$downloadCount, ['expires' => strtotime('+2 week'), 'path' => '/', 'domain' => SITE_DOMAIN, 'secure' => true, 'httponly' => false, 'samesite' => 'Lax']);
|
||||||
|
|
||||||
|
if(!$showThankYouPage){
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exceptions\InvalidFileException){
|
||||||
|
Template::Emit404();
|
||||||
|
}
|
||||||
|
?><?= Template::Header(['downloadUrl' => $downloadUrl]) ?>
|
||||||
|
<main class="donate">
|
||||||
|
<h1>Your download has started!</h1>
|
||||||
|
<div class="thank-you-container">
|
||||||
|
<picture>
|
||||||
|
<? if($ebook->CoverImage2xAvifUrl !== null){ ?><source srcset="<?= $ebook->CoverImage2xAvifUrl ?> 2x, <?= $ebook->CoverImageAvifUrl ?> 1x" type="image/avif"/><? } ?>
|
||||||
|
<source srcset="<?= $ebook->CoverImage2xUrl ?> 2x, <?= $ebook->CoverImageUrl ?> 1x" type="image/jpg"/>
|
||||||
|
<img class="ebook" src="<?= $ebook->CoverImage2xUrl ?>" alt="The cover for the Standard Ebooks edition of <?= Formatter::EscapeHtml(strip_tags($ebook->TitleWithCreditsHtml)) ?>" property="schema:image" height="335" width="224"/>
|
||||||
|
</picture>
|
||||||
|
<div>
|
||||||
|
<p class="stinger">Before you go...</p>
|
||||||
|
<p>Will you <a href="/donate">make a donation</a> to help us further our mission of creating beautiful, free ebooks?</p>
|
||||||
|
<p>It takes a team of highly-skilled volunteers hours to create and proof each of our ebooks. We couldn’t do it without the financial support of literature lovers like you. Any amount helps further our mission!</p>
|
||||||
|
<p class="button-row center">
|
||||||
|
<a href="/donate" class="button">Make a donation towards free literature</a>
|
||||||
|
</p>
|
||||||
|
<p class="stinger">Join the Patrons Circle</p>
|
||||||
|
<p><a href="/donate#patrons-circle">Joining our Patrons Circle</a> gives you access to some awesome book-lover benefits:</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>Your name <a href="/about#patrons-circle">listed on our masthead</a>. (You can also remain anonymous if you prefer.)</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Access to our various <a href="/feeds">ebook feeds</a>:</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>Browse and download from the entire Standard Ebooks catalog directly in your ereading app using our <a href="/feeds/opds">OPDS feed</a>.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Get notified of new ebooks in your news client with our <a href="/feeds/atom">Atom</a> or <a href="/feeds/rss">RSS</a> feeds.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Parse and process the feeds to use our ebooks in your personal software projects.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Access to <a href="/bulk-downloads">bulk ebook downloads</a> to easily download whole collections of ebooks at once.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>The ability to submit a book for inclusion on our <a href="/contribute/wanted-ebooks">Wanted Ebooks list</a>, once per quarter. (Submissions must conform to our <a href="/contribute/collections-policy">collections policy</a> and are subject to approval.)</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>The right to periodically vote on a selection from our <a href="/contribute/wanted-ebooks">Wanted Ebooks list</a> to choose an ebook for immediate production. The resulting ebook will be a permanent addition to our <a href="/ebooks">online catalog of free digital literature</a>.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="button-row center">
|
||||||
|
<a href="/donate#patrons-circle" class="button">Join the S.E. Patrons Circle</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<?= Template::Footer() ?>
|
|
@ -228,7 +228,7 @@ catch(Exceptions\EbookNotFoundException){
|
||||||
<meta property="schema:description" content="epub"/>
|
<meta property="schema:description" content="epub"/>
|
||||||
<meta property="schema:encodingFormat" content="application/epub+zip"/>
|
<meta property="schema:encodingFormat" content="application/epub+zip"/>
|
||||||
<p>
|
<p>
|
||||||
<span><a property="schema:contentUrl" href="<?= $ebook->EpubUrl ?>" class="epub" download="">Compatible epub</a></span> <span>—</span> <span>All devices and apps except Kindles and Kobos.</span>
|
<span><a property="schema:contentUrl" href="<?= $ebook->Url ?>/download?format=<?= EbookFormat::Epub->value ?>" class="epub">Compatible epub</a></span> <span>—</span> <span>All devices and apps except Kindles and Kobos.</span>
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
@ -237,7 +237,7 @@ catch(Exceptions\EbookNotFoundException){
|
||||||
<li property="schema:encoding" typeof="schema:MediaObject">
|
<li property="schema:encoding" typeof="schema:MediaObject">
|
||||||
<meta property="schema:encodingFormat" content="application/x-mobipocket-ebook"/>
|
<meta property="schema:encodingFormat" content="application/x-mobipocket-ebook"/>
|
||||||
<p>
|
<p>
|
||||||
<span><a property="schema:contentUrl" href="<?= $ebook->Azw3Url ?>" class="amazon" download=""><span property="schema:description">azw3</span></a></span> <span>—</span> <span>Kindle devices and apps.<? if($ebook->KindleCoverUrl !== null){ ?> Also download the <a href="<?= $ebook->KindleCoverUrl ?>">Kindle cover thumbnail</a> to see the cover in your Kindle’s library. You may be interested in our <a href="/help/how-to-use-our-ebooks#kindle-faq">Kindle FAQ</a>.<? }else{ ?> Also see our <a href="/how-to-use-our-ebooks#kindle-faq">Kindle FAQ</a>.<? } ?></span>
|
<span><a property="schema:contentUrl" href="<?= $ebook->Url ?>/download?format=<?= EbookFormat::Azw3->value ?>" class="amazon"><span property="schema:description">azw3</span></a></span> <span>—</span> <span>Kindle devices and apps.<? if($ebook->KindleCoverUrl !== null){ ?> Also download the <a href="<?= $ebook->KindleCoverUrl ?>">Kindle cover thumbnail</a> to see the cover in your Kindle’s library. You may be interested in our <a href="/help/how-to-use-our-ebooks#kindle-faq">Kindle FAQ</a>.<? }else{ ?> Also see our <a href="/how-to-use-our-ebooks#kindle-faq">Kindle FAQ</a>.<? } ?></span>
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
@ -246,7 +246,7 @@ catch(Exceptions\EbookNotFoundException){
|
||||||
<li property="schema:encoding" typeof="schema:MediaObject">
|
<li property="schema:encoding" typeof="schema:MediaObject">
|
||||||
<meta property="schema:encodingFormat" content="application/kepub+zip"/>
|
<meta property="schema:encodingFormat" content="application/kepub+zip"/>
|
||||||
<p>
|
<p>
|
||||||
<span><a property="schema:contentUrl" href="<?= $ebook->KepubUrl ?>" class="kobo" download=""><span property="schema:description">kepub</span></a></span> <span>—</span> <span>Kobo devices and apps. You may also be interested in our <a href="/help/how-to-use-our-ebooks#kobo-faq">Kobo FAQ</a>.</span>
|
<span><a property="schema:contentUrl" href="<?= $ebook->Url ?>/download?format=<?= EbookFormat::Kepub->value ?>" class="kobo"><span property="schema:description">kepub</span></a></span> <span>—</span> <span>Kobo devices and apps. You may also be interested in our <a href="/help/how-to-use-our-ebooks#kobo-faq">Kobo FAQ</a>.</span>
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
@ -255,7 +255,7 @@ catch(Exceptions\EbookNotFoundException){
|
||||||
<li property="schema:encoding" typeof="schema:MediaObject">
|
<li property="schema:encoding" typeof="schema:MediaObject">
|
||||||
<meta property="schema:encodingFormat" content="application/epub+zip"/>
|
<meta property="schema:encodingFormat" content="application/epub+zip"/>
|
||||||
<p>
|
<p>
|
||||||
<span><a property="schema:contentUrl" href="<?= $ebook->AdvancedEpubUrl ?>" class="epub" download=""><span property="schema:description">Advanced epub</span></a></span> <span>—</span> <span>An advanced format that uses the latest technology not yet fully supported by most ereaders.</span>
|
<span><a property="schema:contentUrl" href="<?= $ebook->Url ?>/download?format=<?= EbookFormat::AdvancedEpub->value ?>" class="epub"><span property="schema:description">Advanced epub</span></a></span> <span>—</span> <span>An advanced format that uses the latest technology not yet fully supported by most ereaders.</span>
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
|
18
www/ebooks/opensearch.php
Normal file
18
www/ebooks/opensearch.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?
|
||||||
|
header('Content-Type: text/xml; charset=utf-8');
|
||||||
|
print('<?xml version="1.0" encoding="utf-8"?>');
|
||||||
|
?>
|
||||||
|
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||||
|
<ShortName>Standard Ebooks</ShortName>
|
||||||
|
<Description>Search the Standard Ebooks catalog.</Description>
|
||||||
|
<Developer>Standard Ebooks</Developer>
|
||||||
|
<Language>en-US</Language>
|
||||||
|
<SyndicationRight>open</SyndicationRight>
|
||||||
|
<OutputEncoding>UTF-8</OutputEncoding>
|
||||||
|
<InputEncoding>UTF-8</InputEncoding>
|
||||||
|
<Url type="application/xhtml+xml" template="<?= SITE_URL ?>/ebooks?query={searchTerms}&per-page={count}&page={startPage}"/>
|
||||||
|
<Url type="application/rss+xml" template="<?= SITE_URL ?>/feeds/rss/all?query={searchTerms}"/>
|
||||||
|
<Url type="application/atom+xml" template="<?= SITE_URL ?>/feeds/atom/all?query={searchTerms}"/>
|
||||||
|
<Url type="application/atom+xml;profile=opds-catalog;kind=acquisition" template="<?= SITE_URL ?>/feeds/opds/all?query={searchTerms}"/>
|
||||||
|
<Query role="example" searchTerms="fiction" startPage="1" count="12"/>
|
||||||
|
</OpenSearchDescription>
|
Loading…
Add table
Add a link
Reference in a new issue