From e0fbfa44a4ddaaf10b22682c85b9880b345889e7 Mon Sep 17 00:00:00 2001 From: Michael Shavit Date: Sat, 2 May 2020 01:55:14 -0400 Subject: [PATCH 1/8] Fix issue with cover images introduced during the merge of #1277. --- cps/kobo.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cps/kobo.py b/cps/kobo.py index 2e3c1601..3de410d9 100644 --- a/cps/kobo.py +++ b/cps/kobo.py @@ -949,12 +949,15 @@ def HandleInitRequest(): book_uuid="{ImageId}", width="{width}", height="{height}", + Quality='{Quality}', + isGreyscale='isGreyscale', _external=True)) kobo_resources["image_url_template"] = unquote(url_for("kobo.HandleCoverImageRequest", auth_token=kobo_auth.get_auth_token(), book_uuid="{ImageId}", width="{width}", height="{height}", + isGreyscale='false', _external=True)) From 36a984ce3c83c89368ba9ef660a6cb429ef12a17 Mon Sep 17 00:00:00 2001 From: OzzieIsaacs Date: Sat, 2 May 2020 18:17:52 +0200 Subject: [PATCH 2/8] Revert proxyfix --- cps/__init__.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cps/__init__.py b/cps/__init__.py index eee38fdd..ae1378de 100644 --- a/cps/__init__.py +++ b/cps/__init__.py @@ -36,10 +36,6 @@ from flask_principal import Principal from . import config_sql, logger, cache_buster, cli, ub, db from .reverseproxy import ReverseProxied from .server import WebServer -try: - from werkzeug.middleware.proxy_fix import ProxyFix -except ImportError: - from werkzeug.contrib.fixers import ProxyFix mimetypes.init() mimetypes.add_type('application/xhtml+xml', '.xhtml') @@ -80,10 +76,7 @@ log = logger.create() from . import services def create_app(): - try: - app.wsgi_app = ReverseProxied(ProxyFix(app.wsgi_app, x_for=1, x_host=1)) - except (ValueError, TypeError): - app.wsgi_app = ReverseProxied(ProxyFix(app.wsgi_app)) + app.wsgi_app = ReverseProxied(app.wsgi_app) # For python2 convert path to unicode if sys.version_info < (3, 0): app.static_folder = app.static_folder.decode('utf-8') From db38d7ee78dc2a482e1831936a8e45d02c2c79ca Mon Sep 17 00:00:00 2001 From: ElQuimm <50202052+ElQuimm@users.noreply.github.com> Date: Sun, 3 May 2020 21:30:06 +0200 Subject: [PATCH 3/8] Updated version of italian.po :-) --- cps/translations/it/LC_MESSAGES/messages.po | 68 ++++++++++----------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/cps/translations/it/LC_MESSAGES/messages.po b/cps/translations/it/LC_MESSAGES/messages.po index 7ca6e798..e8070740 100644 --- a/cps/translations/it/LC_MESSAGES/messages.po +++ b/cps/translations/it/LC_MESSAGES/messages.po @@ -172,7 +172,7 @@ msgstr "Configurazione del server e-mail aggiornata" #: cps/admin.py:821 msgid "User not found" -msgstr "" +msgstr "Utente non trovato" #: cps/admin.py:842 #, python-format @@ -185,7 +185,7 @@ msgstr "Non rimarrebbe nessun utente amministratore, non posso eliminare l'utent #: cps/admin.py:851 msgid "No admin user remaining, can't remove admin role" -msgstr "" +msgstr "Non rimarrebbe nessun utente amministratore, non posso eliminare il ruolo di amministratore" #: cps/admin.py:887 cps/web.py:1515 msgid "Found an existing account for this e-mail address." @@ -285,11 +285,11 @@ msgstr "non configurato" #: cps/editbooks.py:239 msgid "Book Format Successfully Deleted" -msgstr "" +msgstr "Il formato del libro è stato eliminato con successo" #: cps/editbooks.py:242 msgid "Book Successfully Deleted" -msgstr "" +msgstr "Il libro é stato eliminato con successo" #: cps/editbooks.py:253 cps/editbooks.py:489 msgid "Error opening eBook. File does not exist or file is not accessible" @@ -321,12 +321,12 @@ msgstr "Impossibile creare la cartella %(path)s (autorizzazione negata)." #: cps/editbooks.py:434 #, python-format msgid "Failed to store file %(file)s." -msgstr "Il salvataggio del file %(file)s è fallito." +msgstr "Il salvataggio del file %(file)s non è riuscito." #: cps/editbooks.py:451 #, python-format msgid "File format %(ext)s added to %(book)s" -msgstr "Ho aggiunto l'estensione %(ext)s al libro %(book)s" +msgstr "Ho aggiunto il formato %(ext)s al libro %(book)s" #: cps/editbooks.py:606 msgid "Metadata successfully updated" @@ -362,7 +362,7 @@ msgstr "Il file %(file)s è stato caricato" #: cps/editbooks.py:833 msgid "Source or destination format for conversion missing" -msgstr "Il formato sorgente o quello di destinazione, necessari alla conversione, mancano" +msgstr "Mancano o il formato sorgente o quello di destinazione, necessari alla conversione" #: cps/editbooks.py:841 #, python-format @@ -446,17 +446,17 @@ msgstr "Il file richiesto non può essere letto. I permessi sono corretti?" #: cps/helper.py:299 #, python-format msgid "Deleting book %(id)s failed, path has subfolders: %(path)s" -msgstr "" +msgstr "L'eliminazione del libro %(id)s non è riuscita, poiché il percorso ha delle sottocartelle: %(path)s" #: cps/helper.py:309 #, python-format msgid "Deleting book %(id)s failed: %(message)s" -msgstr "" +msgstr "L'eliminazione del libro %(id)s non è riuscita: %(message)s" #: cps/helper.py:319 #, python-format msgid "Deleting book %(id)s failed, book path not valid: %(path)s" -msgstr "" +msgstr "L'eliminazione del libro %(id)s non è riuscita, poiché il percorso non è valido: %(path)s" #: cps/helper.py:354 #, python-format @@ -489,7 +489,7 @@ msgstr "Errore nel creare la cartella per la copertina" #: cps/helper.py:555 msgid "Cover-file is not a valid image file, or could not be stored" -msgstr "" +msgstr "Il file della copertina non è in un formato immagine valido o non può essere salvato" #: cps/helper.py:566 msgid "Only jpg/jpeg/png/webp files are supported as coverfile" @@ -501,11 +501,11 @@ msgstr "Solamente i file nei formati jpg/jpeg sono supportati per le copertine" #: cps/helper.py:622 msgid "Unrar binary file not found" -msgstr "" +msgstr "Non ho trovato il file binario di UnRar" #: cps/helper.py:635 msgid "Error excecuting UnRar" -msgstr "" +msgstr "Errore nell'eseguire UnRar" #: cps/helper.py:691 msgid "Waiting" @@ -558,19 +558,19 @@ msgstr "Registra con %(provider)s" #: cps/oauth_bb.py:154 msgid "Failed to log in with GitHub." -msgstr "Accesso con GitHub non riuscito." +msgstr "Accesso con GitHub non è riuscito." #: cps/oauth_bb.py:159 msgid "Failed to fetch user info from GitHub." -msgstr "Fallito il recupero delle informazioni dell'utente da GitHub." +msgstr "Il recupero delle informazioni dell'utente da GitHub non è riuscito." #: cps/oauth_bb.py:170 msgid "Failed to log in with Google." -msgstr "Fallito l'accesso con Google." +msgstr "L'accesso con Google non è riuscito." #: cps/oauth_bb.py:175 msgid "Failed to fetch user info from Google." -msgstr "Fallito il recupero delle informazioni dell'utente da Google." +msgstr "Il recupero delle informazioni dell'utente da Google non è riuscito." #: cps/oauth_bb.py:225 cps/web.py:1291 cps/web.py:1431 #, python-format @@ -584,7 +584,7 @@ msgstr "Collegamento a %(oauth)s avvenuto con successo" #: cps/oauth_bb.py:241 msgid "Login failed, No User Linked With OAuth Account" -msgstr "Accesso fallito, non c'è un utente collegato all'account OAuth" +msgstr "Accesso non riuscito, non c'è un utente collegato all'account OAuth" #: cps/oauth_bb.py:283 #, python-format @@ -594,7 +594,7 @@ msgstr "Scollegamento da %(oauth)s avvenuto con successo" #: cps/oauth_bb.py:287 #, python-format msgid "Unlink to %(oauth)s Failed" -msgstr "Scollegamento da %(oauth)s fallito" +msgstr "Scollegamento da %(oauth)s non riuscito" #: cps/oauth_bb.py:290 #, python-format @@ -818,11 +818,11 @@ msgstr "Mostra la selezione del formato dei file" #: cps/ub.py:107 cps/web.py:1150 msgid "Archived Books" -msgstr "" +msgstr "Libri archiviati" #: cps/ub.py:109 msgid "Show archived books" -msgstr "" +msgstr "Mostra l'opzione per la selezione dei libri archiviati" #: cps/updater.py:294 cps/updater.py:305 cps/updater.py:406 cps/updater.py:420 msgid "Unexpected data while reading update information" @@ -1360,23 +1360,23 @@ msgstr "Descrizione" #: cps/templates/book_edit.html:66 msgid "Identifiers" -msgstr "" +msgstr "Identificatori" #: cps/templates/book_edit.html:70 cps/templates/book_edit.html:308 msgid "Identifier Type" -msgstr "" +msgstr "Tipo di identificatore" #: cps/templates/book_edit.html:71 cps/templates/book_edit.html:309 msgid "Identifier Value" -msgstr "" +msgstr "Valore dell'identificatore" #: cps/templates/book_edit.html:72 cps/templates/book_edit.html:310 msgid "Remove" -msgstr "" +msgstr "Rimuovi" #: cps/templates/book_edit.html:76 msgid "Add Identifier" -msgstr "" +msgstr "Aggiungi un identificatore" #: cps/templates/book_edit.html:80 cps/templates/search_form.html:33 msgid "Tags" @@ -1453,11 +1453,11 @@ msgstr "e dal disco rigido" #: cps/templates/book_edit.html:209 msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." -msgstr "" +msgstr "Oservazione importante riguardo Kobo: i libri eliminati, rimarranno in ogni lettore Kobo accoppiato." #: cps/templates/book_edit.html:210 msgid "Books must first be archived and the device synced before a book can safely be deleted." -msgstr "" +msgstr "Prima di poter elimnare in sicurezza un libro, prima occorre che il libro venga archiviato e che l'apparecchio venga sincronizzato." #: cps/templates/book_edit.html:232 msgid "Keyword" @@ -1775,7 +1775,7 @@ msgstr "Percorso del convertitore" #: cps/templates/config_edit.html:349 msgid "Location of Unrar binary" -msgstr "Percorso di UnRar" +msgstr "Percorso del file binario di UnRar" #: cps/templates/config_edit.html:368 cps/templates/layout.html:84 #: cps/templates/login.html:4 cps/templates/login.html:20 @@ -1912,15 +1912,15 @@ msgstr "da leggere" #: cps/templates/detail.html:208 msgid "Restore from archive" -msgstr "" +msgstr "Ripristina dall'archivio" #: cps/templates/detail.html:208 msgid "Add to archive" -msgstr "" +msgstr "Aggiungi all'archivio" #: cps/templates/detail.html:209 msgid "Archived" -msgstr "" +msgstr "Archiviato" #: cps/templates/detail.html:219 msgid "Description:" @@ -2252,7 +2252,7 @@ msgstr "Scuro" #: cps/templates/readcbr.html:121 msgid "Scale" -msgstr "Adatta" +msgstr "Scala" #: cps/templates/readcbr.html:124 msgid "Best" @@ -2396,7 +2396,7 @@ msgstr "Cambia ordine" #: cps/templates/shelf.html:67 msgid "Are you sure you want to delete this shelf?" -msgstr "Vuoi davvero eliminare lo scaffale?" +msgstr "Vuoi davvero eliminare questo scaffale?" #: cps/templates/shelf.html:70 msgid "Shelf will be deleted for all users" From fb16429867b1255ef1074bdf0fd29fd32b4b4189 Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Mon, 4 May 2020 19:02:03 +0200 Subject: [PATCH 4/8] Randomize flask secret_key --- cps/__init__.py | 2 +- cps/config_sql.py | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cps/__init__.py b/cps/__init__.py index ae1378de..7dd4e11f 100644 --- a/cps/__init__.py +++ b/cps/__init__.py @@ -88,7 +88,7 @@ def create_app(): log.info('Starting Calibre Web...') Principal(app) lm.init_app(app) - app.secret_key = os.getenv('SECRET_KEY', 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT') + app.secret_key = os.getenv('SECRET_KEY', config_sql.get_flask_session_key(ub.session)) web_server.init_app(app, config) db.setup_db(config) diff --git a/cps/config_sql.py b/cps/config_sql.py index 241e583a..590b8eea 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -22,7 +22,7 @@ import os import json import sys -from sqlalchemy import exc, Column, String, Integer, SmallInteger, Boolean +from sqlalchemy import exc, Column, String, Integer, SmallInteger, Boolean, BLOB from sqlalchemy.ext.declarative import declarative_base from . import constants, cli, logger, ub @@ -31,6 +31,15 @@ from . import constants, cli, logger, ub log = logger.create() _Base = declarative_base() +class _Flask_Settings(_Base): + __tablename__ = 'flask_settings' + + id = Column(Integer, primary_key=True) + flask_session_key = Column(BLOB, default="") + + def __init__(self, key): + self.flask_session_key = key + # Baseclass for representing settings in app.db with email server settings and Calibre database settings # (application settings) @@ -301,7 +310,7 @@ def _migrate_table(session, orm_class): log.debug("%s: %s", column_name, err.args[0]) if column.default is not None: if sys.version_info < (3, 0): - if isinstance(column.default.arg,unicode): + if isinstance(column.default.arg, unicode): column.default.arg = column.default.arg.encode('utf-8') if column.default is None: column_default = "" @@ -337,6 +346,7 @@ def _migrate_database(session): # make sure the table is created, if it does not exist _Base.metadata.create_all(session.bind) _migrate_table(session, _Settings) + _migrate_table(session, _Flask_Settings) def load_configuration(session): @@ -354,3 +364,11 @@ def load_configuration(session): update({"denied_tags": conf.config_mature_content_tags}, synchronize_session=False) session.commit() return conf + +def get_flask_session_key(session): + flask_settings = session.query(_Flask_Settings).one_or_none() + if flask_settings == None: + flask_settings = _Flask_Settings(os.urandom(32)) + session.add(flask_settings) + session.commit() + return flask_settings.flask_session_key From 850a85915be0e3dd9cf665ce4fa827a11124d71d Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Tue, 5 May 2020 18:48:40 +0200 Subject: [PATCH 5/8] Fix #1354 (Error on uploading single book, because of missing rarfile) --- cps/editbooks.py | 2 +- cps/helper.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cps/editbooks.py b/cps/editbooks.py index d66763bf..2204ce1e 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -453,7 +453,7 @@ def upload_single_file(request, book, book_id): "" + uploadText + "") return uploader.process( - saved_filename, *os.path.splitext(requested_file.filename)) + saved_filename, *os.path.splitext(requested_file.filename), config.config_rarfile_location) def upload_cover(request, book): diff --git a/cps/helper.py b/cps/helper.py index 435b1322..c89bdf3d 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -292,6 +292,7 @@ def delete_book_file(book, calibrepath, book_format=None): for file in os.listdir(path): if file.upper().endswith("."+book_format): os.remove(os.path.join(path, file)) + return True, None else: if os.path.isdir(path): if len(next(os.walk(path))[1]): From 0735fb1e929fd673397acdd7e2c1c8be0d510d3f Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Tue, 5 May 2020 18:55:28 +0200 Subject: [PATCH 6/8] Fix #1349 (Fix error on move cover with foreign file systems, e.g. samba shares) Preparation for release --- cps/constants.py | 2 +- cps/editbooks.py | 23 ++++++----- test/Calibre-Web TestSummary.html | 66 ++++++++++++++++--------------- 3 files changed, 48 insertions(+), 43 deletions(-) mode change 100644 => 100755 test/Calibre-Web TestSummary.html diff --git a/cps/constants.py b/cps/constants.py index 586172f7..4de6b7a1 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -129,7 +129,7 @@ def selected_roles(dictionary): BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' 'series_id, languages') -STABLE_VERSION = {'version': '0.6.7 Beta'} +STABLE_VERSION = {'version': '0.6.7'} NIGHTLY_VERSION = {} NIGHTLY_VERSION[0] = '$Format:%H$' diff --git a/cps/editbooks.py b/cps/editbooks.py index 2204ce1e..d6b18f93 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -702,16 +702,11 @@ def upload(): return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') try: copyfile(meta.file_path, saved_filename) - except OSError: - log.error("Failed to store file %s (Permission denied)", saved_filename) - flash(_(u"Failed to store file %(file)s (Permission denied).", file=saved_filename), category="error") - return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') - try: os.unlink(meta.file_path) - except OSError: - log.error("Failed to delete file %(file)s (Permission denied)", meta.file_path) - flash(_(u"Failed to delete file %(file)s (Permission denied).", file= meta.file_path), - category="warning") + except OSError as e: + log.error("Failed to move file %s: %s", saved_filename, e) + flash(_(u"Failed to Move File %(file)s: %(error)s", file=saved_filename, error=e), category="error") + return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') if meta.cover is None: has_cover = 0 @@ -719,7 +714,15 @@ def upload(): os.path.join(filepath, "cover.jpg")) else: has_cover = 1 - move(meta.cover, os.path.join(filepath, "cover.jpg")) + try: + copyfile(meta.cover, os.path.join(filepath, "cover.jpg")) + os.unlink(meta.cover) + except OSError as e: + log.error("Failed to move cover file %s: %s", os.path.join(filepath, "cover.jpg"), e) + flash(_(u"Failed to Move Cover File %(file)s: %(error)s", file=os.path.join(filepath, "cover.jpg"), + error=e), + category="error") + return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') # handle authors is_author = db.session.query(db.Authors).filter(db.Authors.name == authr).first() diff --git a/test/Calibre-Web TestSummary.html b/test/Calibre-Web TestSummary.html old mode 100644 new mode 100755 index ea31b506..4f560221 --- a/test/Calibre-Web TestSummary.html +++ b/test/Calibre-Web TestSummary.html @@ -36,17 +36,17 @@
-

Start Time: 2020-05-01 13:35:57

+

Start Time: 2020-05-05 19:02:03

-

Stop Time: 2020-05-01 14:32:26

+

Stop Time: 2020-05-05 19:58:37

-

Duration: 47:49 min

+

Duration: 47:42 min

@@ -1829,8 +1829,8 @@ AssertionError: False is not true : logfile config value is not empty after rese test_updater.test_updater 7 - 6 - 0 + 5 + 1 0 1 @@ -1867,11 +1867,33 @@ AssertionError: False is not true : logfile config value is not empty after rese - +
test_check_update_stable_versions
- PASS + +
+ FAIL +
+ + + + @@ -1924,8 +1946,8 @@ AssertionError: False is not true : logfile config value is not empty after rese test_user_template.test_user_template 19 - 18 - 1 + 19 + 0 0 0 @@ -2088,31 +2110,11 @@ AssertionError: False is not true : logfile config value is not empty after rese - +
test_series_user_template
- -
- FAIL -
- - - - + PASS @@ -2574,7 +2576,7 @@ AssertionError: False is not true SQLAlchemy-Utils - 0.36.4 + 0.36.5 test_OAuth_login From 51808d2ad44f0f7d8a064681d5edad2f23b721fb Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Tue, 5 May 2020 20:31:12 +0200 Subject: [PATCH 7/8] Version Bump --- cps/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cps/constants.py b/cps/constants.py index 4de6b7a1..a3bd0da0 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -129,7 +129,7 @@ def selected_roles(dictionary): BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' 'series_id, languages') -STABLE_VERSION = {'version': '0.6.7'} +STABLE_VERSION = {'version': '0.6.8 Beta'} NIGHTLY_VERSION = {} NIGHTLY_VERSION[0] = '$Format:%H$' From 6a6c1b6b2139e927c4344d5b7d23bbb44871090a Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Wed, 6 May 2020 16:25:03 +0200 Subject: [PATCH 8/8] Fix for #1358, #1355 --- cps/editbooks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cps/editbooks.py b/cps/editbooks.py index d6b18f93..c7321a2a 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -453,7 +453,8 @@ def upload_single_file(request, book, book_id): "" + uploadText + "") return uploader.process( - saved_filename, *os.path.splitext(requested_file.filename), config.config_rarfile_location) + saved_filename, *os.path.splitext(requested_file.filename), + rarExcecutable=config.config_rarfile_location) def upload_cover(request, book):