diff --git a/dist/files_opds-0.5.tar.gz b/dist/files_opds-0.5.tar.gz
new file mode 100644
index 0000000..dda5260
Binary files /dev/null and b/dist/files_opds-0.5.tar.gz differ
diff --git a/files_opds/admin.php b/files_opds/admin.php
index 575d9a2..8242395 100644
--- a/files_opds/admin.php
+++ b/files_opds/admin.php
@@ -25,6 +25,7 @@ $formats = array(
$tmpl = new \OCP\Template('files_opds', 'admin');
$tmpl->assign('feedSubtitle', Config::getApp('feed-subtitle', $l->t("%s OPDS catalog", $defaults->getName())));
+$tmpl->assign('isbndbKey', Config::getApp('isbndb-key', ''));
$tmpl->assign('previewFormats', $formats);
$tmpl->assign('cover-x', Config::getApp('cover-x', '200'));
$tmpl->assign('cover-y', Config::getApp('cover-y', '200'));
diff --git a/files_opds/ajax/admin.php b/files_opds/ajax/admin.php
index 370fe2a..91d8a48 100644
--- a/files_opds/ajax/admin.php
+++ b/files_opds/ajax/admin.php
@@ -25,12 +25,14 @@ if (isset($_POST['opdsCoverX'])) {
$opdsThumbX = isset($_POST['opdsThumbX']) ? (int) $_POST['opdsThumbX'] : 36;
$opdsThumbY = isset($_POST['opdsThumbY']) ? (int) $_POST['opdsThumbY'] : 36;
$opdsFeedSubtitle = isset($_POST['opdsFeedSubtitle']) ? $_POST['opdsFeedSubtitle'] : $l->t("%s OPDS catalog", $defaults->getName());
+ $opdsIsbndbKey = isset($_POST['opdsIsbndbKey']) ? $_POST['opdsIsbndbKey'] : '';
Config::setApp('cover-x', $opdsCoverX);
Config::setApp('cover-y', $opdsCoverY);
Config::setApp('thumb-x', $opdsThumbX);
Config::setApp('thumb-y', $opdsThumbX);
Config::setApp('feed_subtitle', $opdsFeedSubtitle);
+ Config::setApp('isbndb-key', $opdsIsbndbKey);
} else {
// set preview preferences
$opdsPreviewEpub = $_POST['opdsPreviewEpub'];
diff --git a/files_opds/appinfo/database.xml b/files_opds/appinfo/database.xml
index fda2e97..c689103 100644
--- a/files_opds/appinfo/database.xml
+++ b/files_opds/appinfo/database.xml
@@ -12,8 +12,8 @@
id
integer
- 0
true
+ true
11
@@ -105,6 +105,22 @@
true
1024
+
+
+
+ rescan
+ timestamp
+
+ false
+
+
+
+ opds_metadata_id_index
+
+ id
+
+
+
diff --git a/files_opds/appinfo/info.xml b/files_opds/appinfo/info.xml
index 1613baf..f1f0524 100644
--- a/files_opds/appinfo/info.xml
+++ b/files_opds/appinfo/info.xml
@@ -4,11 +4,20 @@
OPDS catalog
Personal OPDS catalog
AGPL
- 0.4
+ 0.5
Frank de Lange
7.0
true
+ https://github.com/Yetangitu/owncloud-apps
+ https://github.com/Yetangitu/owncloud-apps/issues
+ https://github.com/Yetangitu/owncloud-apps
+
+
+ pgsql
+ sqlite3
+ mysql
+
168132
diff --git a/files_opds/js/admin.js b/files_opds/js/admin.js
index 598ce9f..dd95ca7 100644
--- a/files_opds/js/admin.js
+++ b/files_opds/js/admin.js
@@ -27,7 +27,8 @@ $(document).ready(function(){
opdsCoverY : $('#opds-cover-y').val(),
opdsThumbX : $('#opds-thumb-x').val(),
opdsThumbY : $('#opds-thumb-y').val(),
- opdsFeedSubtitle : $('#opds-feed-subtitle').val()
+ opdsFeedSubtitle : $('#opds-feed-subtitle').val(),
+ opdsIsbndbKey : $('#opds-isbndb-key').val()
};
OC.msg.startSaving('#opds-admin .msg');
$.post(OC.filePath('files_opds', 'ajax', 'admin.php'), data, opdsAdminCoverSettings.afterSave);
@@ -42,8 +43,8 @@ $(document).ready(function(){
$('#opds-preview-opendocument').on("change", opdsAdminSettings.save);
$('#opds-preview-msoffice').on("change", opdsAdminSettings.save);
- $('#opds-cover-x,#opds-cover-y,#opds-thumb-x,#opds-thumb-y,#opds-feed-subtitle').blur(opdsAdminCoverSettings.save);
- $('#opds-cover-x,#opds-cover-y,#opds-thumb-x,#opds-thumb-y,#opds-feed-subtitle').keypress(function( event ) {
+ $('#opds-cover-x,#opds-cover-y,#opds-thumb-x,#opds-thumb-y,#opds-feed-subtitle,#opds-isbndb-key').blur(opdsAdminCoverSettings.save);
+ $('#opds-cover-x,#opds-cover-y,#opds-thumb-x,#opds-thumb-y,#opds-feed-subtitle,#opds-isbndb-key').keypress(function( event ) {
if (event.which == 13) {
event.preventDefault();
opdsAdminCoverSettings.save();
diff --git a/files_opds/lib/google.php b/files_opds/lib/google.php
new file mode 100644
index 0000000..4de70ea
--- /dev/null
+++ b/files_opds/lib/google.php
@@ -0,0 +1,92 @@
+ 0) {
+ self::parse($isbn,$meta);
+ return true;
+ } else {
+ $meta['rescan'] = date("Y-m-d\TH:i:sP", time() + Isbn::RESCAN_NOT_FOUND);
+ }
+
+ return false;
+ }
+
+ /**
+ * @brief parse Google response into OPDS $meta array
+ *
+ * @param array $data Google response (json_decoded into array)
+ * @param arrayref &$meta OPDS metadata array
+ * @return int errorcode (0 if success)
+ */
+ static function parse($data,&$meta) {
+ foreach ($data as $key => $value) {
+ switch ($key) {
+ case 'description':
+ $meta['description'] = $value;
+ if(array_key_exists('notes',$data)) {
+ $meta['description'] .= ((trim($value) == false) ? '' : "\n\n") . $data['notes'];
+ }
+ break;
+ case 'subject_ids':
+ $meta['subjects'] = json_encode($value);
+ break;
+ /* rather pointless, ISBN is what brought us here in the first place and is alread set
+ case 'industryIdentifiers':
+ foreach($value as $array) {
+ if ($array['type'] = 'ISBN_13') {
+ $isbn13 = $array['identifier'];
+ } elseif ($array['type'] = 'ISBN_10') {
+ $isbn10 = $array['identifier'];
+ }
+ }
+
+ $meta['isbn'] = (isset($isbn13)) ? $isbn13 : $isbn10;
+ break;
+ */
+ case 'title':
+ $meta['title'] = $value;
+ break;
+ case 'authors':
+ $meta['author'] = json_encode($value);
+ break;
+ case 'language':
+ $meta['language'] = $value;
+ break;
+ case 'publisher':
+ $meta['publisher'] = $value;
+ break;
+ case 'publishedDate':
+ $meta['date'] = $value;
+ break;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/files_opds/lib/isbn.php b/files_opds/lib/isbn.php
new file mode 100644
index 0000000..b2a3e25
--- /dev/null
+++ b/files_opds/lib/isbn.php
@@ -0,0 +1,154 @@
+ $value) {
+ switch ($key) {
+ case 'summary':
+ $meta['description'] = $value;
+ if(array_key_exists('notes',$data)) {
+ $meta['description'] .= ((trim($value) == false) ? '' : "\n\n") . $data['notes'];
+ }
+ break;
+ case 'subject_ids':
+ $meta['subjects'] = json_encode($value);
+ break;
+ case 'isbn10':
+ if(!(array_key_exists('isbn13', $data))) {
+ $meta['isbn'] = $value;
+ }
+ break;
+ case 'isbn13':
+ $meta['isbn'] = $value;
+ break;
+ case 'title':
+ if(!(array_key_exists('title_long',$data))) {
+ $meta['title'] = $value;
+ }
+ break;
+ case 'title_long':
+ $meta['title'] = $value;
+ break;
+ case 'author_data':
+ $meta['author'] = json_encode(array_column($value, 'name','id'));
+ break;
+ case 'language':
+ $meta['language'] = $value;
+ break;
+ case 'publisher_name':
+ $meta['publisher'] = $value;
+ if(array_key_exists('publisher_text',$data)) {
+ $meta['publisher'] .= ((trim($value) == false) ? '' : ', ') . $data['publisher_text'];
+ }
+ break;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/files_opds/lib/meta.php b/files_opds/lib/meta.php
index 76d460b..1ebdca8 100644
--- a/files_opds/lib/meta.php
+++ b/files_opds/lib/meta.php
@@ -40,6 +40,7 @@ class Meta
$meta['copyright'] = '';
$meta['description'] = '';
$meta['subjects'] = '';
+ $meta['rescan'] = null;
return $meta;
}
@@ -65,20 +66,45 @@ class Meta
* @return OC_DB_StatementWrapper
*/
protected static function save($meta) {
- $sql = "INSERT INTO *PREFIX*opds_metadata (`id`, `updated`, `date`, `author`, `title`, `language`, `publisher`, `isbn`, `copyright`, `description`, `subjects`) VALUES (?,?,?,?,?,?,?,?,?,?,?)";
- $args = array(
- $meta['id'],
- $meta['updated'],
- $meta['date'],
- $meta['author'],
- $meta['title'],
- $meta['language'],
- $meta['publisher'],
- $meta['isbn'],
- $meta['copyright'],
- $meta['description'],
- $meta['subjects']
- );
+ $sql = "SELECT `id` FROM *PREFIX*opds_metadata WHERE `id`=?";
+ $args = array($meta['id']);
+ $query = \OCP\DB::prepare($sql);
+ $result = $query->execute($args);
+ $data = $result->fetchRow();
+ if (isset($data['id'])) {
+ $sql = "UPDATE *PREFIX*opds_metadata SET `updated`=?, `date`=?, `author`=?, `title`=?, `language`=?, `publisher`=?, `isbn`=?, `copyright`=?, `description`=?, `subjects`=?, `rescan`=? WHERE id=?";
+ $args = array(
+ $meta['updated'],
+ $meta['date'],
+ $meta['author'],
+ $meta['title'],
+ $meta['language'],
+ $meta['publisher'],
+ $meta['isbn'],
+ $meta['copyright'],
+ $meta['description'],
+ $meta['subjects'],
+ $meta['rescan'],
+ $meta['id']
+ );
+
+ } else {
+ $sql = "INSERT INTO *PREFIX*opds_metadata (`id`, `updated`, `date`, `author`, `title`, `language`, `publisher`, `isbn`, `copyright`, `description`, `subjects`, `rescan`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
+ $args = array(
+ $meta['id'],
+ $meta['updated'],
+ $meta['date'],
+ $meta['author'],
+ $meta['title'],
+ $meta['language'],
+ $meta['publisher'],
+ $meta['isbn'],
+ $meta['copyright'],
+ $meta['description'],
+ $meta['subjects'],
+ $meta['rescan']
+ );
+ }
$query = \OCP\DB::prepare($sql);
return $query->execute($args);
@@ -93,7 +119,10 @@ class Meta
* @return array of metadata
*/
public static function get($id) {
- if (!($meta = self::load($id))) {
+ if (!($meta = self::load($id)) || (isset($meta['rescan']) && time() > $meta['rescan'])) {
+ if(isset($meta['rescan'])) {
+ $meta['rescan'] = null;
+ }
$meta = self::scan($id);
}
return $meta;
@@ -101,8 +130,6 @@ class Meta
/**
* @brief scan files for metadata
- * PLAN: use search_lucene to extract metadata? Does not seem to support PDF1.6?
- * solution: first ask search_lucene, if no data then scan file?
*
* @param int $id fileid
* @return array $meta metadata
@@ -110,16 +137,19 @@ class Meta
public static function scan($id) {
$meta = self::create($id);
$path = \OC\Files\Filesystem::getLocalFile(\OC\Files\Filesystem::getPath($id));
-
- switch (strtolower(substr(strrchr($path, "."), 1))) {
- case 'epub':
- self::epub($path,$meta);
- break;
- case 'pdf':
- self::pdf($path,$meta);
- break;
- }
+ /* try to call function named 'type' with signature type($path,$meta)
+ * eg, pdf(), epub(), etc
+ */
+ $type = strtolower(substr(strrchr($path, "."), 1));
+ if(is_callable(array(__CLASS__, $type))) {
+ try {
+ self::$type($path,$meta);
+ } catch (Exception $e) {
+ Util::logWarn("no metadata scanner for format " . $type);
+ }
+ }
+
/* if title is not set, assume metadata was invalid or not present
* use filename as title
*/
@@ -127,7 +157,7 @@ class Meta
$info = pathinfo($path);
$meta['title'] = basename($path,'.'.$info['extension']);
}
- // self::save($meta);
+ self::save($meta);
return $meta;
}
@@ -137,21 +167,23 @@ class Meta
*
* @param string $path path to epub
* @param arrayref $meta reference to array of metadata
- * @return bool $success (true if metadata found)
*/
public static function epub($path,&$meta) {
+ $success = false;
$epub = new Epub($path);
- $meta['author'] = json_encode($epub->Authors());
- $meta['title'] = $epub->Title();
- $meta['date'] = $epub->Date();
- $meta['publisher'] = $epub->Publisher();
- $meta['copyright'] = $epub->Copyright();
- $meta['language'] = $epub->Language();
- $meta['description'] = strip_tags($epub->Description());
- $meta['isbn'] = $epub->ISBN();
- $meta['subjects'] = $epub->Subjects();
-
- return true;
+ /* first try ISBN */
+ if(!(($isbn = $epub->ISBN()) && (Isbn::get($isbn, $meta)))) {
+ /* use EPUB internal metadata instead */
+ $meta['author'] = json_encode($epub->Authors());
+ $meta['title'] = $epub->Title();
+ $meta['date'] = $epub->Date();
+ $meta['publisher'] = $epub->Publisher();
+ $meta['copyright'] = $epub->Copyright();
+ $meta['language'] = $epub->Language();
+ $meta['description'] = strip_tags($epub->Description());
+ $meta['isbn'] = $epub->ISBN();
+ $meta['subjects'] = json_encode($epub->Subjects());
+ }
}
/**
@@ -159,10 +191,45 @@ class Meta
*
* @param string $path path to pdf
* @param arrayref $meta reference to array of metadata
- * @return bool $success (true if metadata found)
*/
public static function pdf($path,&$meta) {
+ if(\OC_Util::runningOnWindows()) {
+ /* not supported when running on Windows due to use of exec() */
+ return;
+ }
- return false;
+ /* first, try to get metadata through ISBN */
+ $command = ['pdftotext -l 10 "','" -'];
+ $output=array();
+ exec($command[0] . $path . $command[1], $output);
+ if (!(($output) && ($isbn = Isbn::scan($output)) && (Isbn::get($isbn,$meta)))) {
+ /* No ISBN, try PDF metadata */
+ $output=array();
+ $command = ["pdfinfo '","'|grep -we '^\(Title\|Author\|Subject\|Keywords\|CreationDate\|ModDate\)'"];
+ exec($command[0] . $path . $command[1], $output);
+ foreach($output as $data) {
+ list($key, $value) = explode(':',$data,2);
+ $value = trim($value);
+ }
+
+ if (!($value == '')) {
+ switch ($key) {
+ case 'Title':
+ $meta['title'] = $value;
+ break;
+ case 'Author':
+ $meta['author'] = $value;
+ break;
+ case 'Subject':
+ case 'Keywords':
+ $meta['subjects'] .= $value;
+ break;
+ case 'CreationDate':
+ case 'ModDate':
+ $meta['date'] = strtotime($value);
+ break;
+ }
+ }
+ }
}
}
diff --git a/files_opds/templates/admin.php b/files_opds/templates/admin.php
index d8f4886..13f60ce 100644
--- a/files_opds/templates/admin.php
+++ b/files_opds/templates/admin.php
@@ -23,10 +23,16 @@ function checkBox($format) {
t('OPDS')); ?>
-
-
- " value="" />
-
+
t('Enable preview for:')); ?>
diff --git a/files_opds/templates/part.feed.acquisition.php b/files_opds/templates/part.feed.acquisition.php
index 83c18eb..b0bff3d 100644
--- a/files_opds/templates/part.feed.acquisition.php
+++ b/files_opds/templates/part.feed.acquisition.php
@@ -3,15 +3,21 @@
id:
-
-
urn:isbn:
-
-
+
+
urn:isbn:
+
+
+
+
+
+
+
+