diff --git a/cps/MyLoginManager.py b/cps/MyLoginManager.py
index 419b2e90..44907045 100644
--- a/cps/MyLoginManager.py
+++ b/cps/MyLoginManager.py
@@ -19,14 +19,11 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import ast
-import hashlib
from .cw_login import LoginManager
from flask import session
-
class MyLoginManager(LoginManager):
def _session_protection_failed(self):
sess = session._get_current_object()
diff --git a/cps/cw_login/login_manager.py b/cps/cw_login/login_manager.py
index bf0efbc7..21dc803d 100644
--- a/cps/cw_login/login_manager.py
+++ b/cps/cw_login/login_manager.py
@@ -397,7 +397,7 @@ class LoginManager:
def _load_user_from_remember_cookie(self, cookie):
signer_kwargs = dict(
- key_derivation="hmac", digest_method=staticmethod(hashlib.sha1)
+ key_derivation="hmac", digest_method=hashlib.sha1
)
try:
remember_dict = URLSafeSerializer(
@@ -482,7 +482,7 @@ class LoginManager:
# prepare data
max_age = int(current_app.permanent_session_lifetime.total_seconds())
signer_kwargs = dict(
- key_derivation="hmac", digest_method=staticmethod(hashlib.sha1)
+ key_derivation="hmac", digest_method=hashlib.sha1
)
# save
data = URLSafeSerializer(
diff --git a/cps/editbooks.py b/cps/editbooks.py
index 84299c63..5f58cf81 100644
--- a/cps/editbooks.py
+++ b/cps/editbooks.py
@@ -134,8 +134,9 @@ def edit_book(book_id):
# handle upload other formats from local disk
meta = upload_single_file(request, book, book_id)
# only merge metadata if file was uploaded and no error occurred (meta equals not false or none)
+ upload_format = False
if meta:
- merge_metadata(to_save, meta)
+ upload_format = merge_metadata(to_save, meta)
# handle upload covers from local disk
cover_upload_success = upload_cover(request, book)
if cover_upload_success:
@@ -179,7 +180,7 @@ def edit_book(book_id):
modify_date |= edit_book_publisher(to_save['publisher'], book)
# handle book languages
try:
- modify_date |= edit_book_languages(to_save['languages'], book)
+ modify_date |= edit_book_languages(to_save['languages'], book, upload_format)
except ValueError as e:
flash(str(e), category="error")
edit_error = True
@@ -575,6 +576,10 @@ def merge_metadata(to_save, meta):
to_save['author_name'] = ''
if to_save.get('book_title', "") == _('Unknown'):
to_save['book_title'] = ''
+ if not to_save["languages"] and meta.languages:
+ upload_language = True
+ else:
+ upload_language = False
for s_field, m_field in [
('tags', 'tags'), ('author_name', 'author'), ('series', 'series'),
('series_index', 'series_id'), ('languages', 'languages'),
@@ -582,7 +587,7 @@ def merge_metadata(to_save, meta):
to_save[s_field] = to_save[s_field] or getattr(meta, m_field, '')
to_save["description"] = to_save["description"] or Markup(
getattr(meta, 'description', '')).unescape()
-
+ return upload_language
def identifier_list(to_save, book):
"""Generate a list of Identifiers from form information"""
diff --git a/cps/embed_helper.py b/cps/embed_helper.py
index 71de216d..54db47ef 100644
--- a/cps/embed_helper.py
+++ b/cps/embed_helper.py
@@ -28,7 +28,7 @@ log = logger.create()
def do_calibre_export(book_id, book_format):
try:
- quotes = [3, 5, 7, 9]
+ quotes = [4, 6]
tmp_dir = get_temp_dir()
calibredb_binarypath = get_calibre_binarypath("calibredb")
temp_file_name = str(uuid4())
diff --git a/cps/helper.py b/cps/helper.py
index 08fa1387..004e1b0e 100644
--- a/cps/helper.py
+++ b/cps/helper.py
@@ -413,36 +413,6 @@ def rename_all_files_on_change(one_book, new_path, old_path, all_new_name, gdriv
file_format.name = all_new_name
-'''def rename_all_authors(first_author, renamed_author, calibre_path="", localbook=None, gdrive=False):
- # Create new_author_dir from parameter or from database
- # Create new title_dir from database and add id
- if first_author:
- new_authordir = get_valid_filename(first_author, chars=96)
- for r in renamed_author:
- new_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == r).first()
- old_author_dir = get_valid_filename(r, chars=96)
- new_author_rename_dir = get_valid_filename(new_author.name, chars=96)
- if gdrive:
- g_file = gd.getFileFromEbooksFolder(None, old_author_dir)
- if g_file:
- gd.moveGdriveFolderRemote(g_file, new_author_rename_dir)
- gd.updateDatabaseOnEdit(g_file['id'], new_author_rename_dir)
- else:
- if os.path.isdir(os.path.join(calibre_path, old_author_dir)):
- old_author_path = os.path.join(calibre_path, old_author_dir)
- new_author_path = os.path.join(calibre_path, new_author_rename_dir)
- try:
- shutil.move(os.path.normcase(old_author_path), os.path.normcase(new_author_path))
- except OSError as ex:
- log.error("Rename author from: %s to %s: %s", old_author_path, new_author_path, ex)
- log.debug(ex, exc_info=True)
- return _("Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s",
- src=old_author_path, dest=new_author_path, error=str(ex))
- else:
- new_authordir = get_valid_filename(localbook.authors[0].name, chars=96)
- return new_authordir'''
-
-
def rename_author_path(first_author, old_author_dir, renamed_author, calibre_path="", gdrive=False):
# Create new_author_dir from parameter or from database
# Create new title_dir from database and add id
@@ -459,12 +429,15 @@ def rename_author_path(first_author, old_author_dir, renamed_author, calibre_pat
old_author_path = os.path.join(calibre_path, old_author_dir)
new_author_path = os.path.join(calibre_path, new_author_rename_dir)
try:
- shutil.move(old_author_path, new_author_path)
- except OSError as ex:
- log.error("Rename author from: %s to %s: %s", old_author_path, new_author_path, ex)
- log.debug(ex, exc_info=True)
- return _("Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s",
- src=old_author_path, dest=new_author_path, error=str(ex))
+ os.rename(old_author_path, new_author_path)
+ except OSError:
+ try:
+ shutil.move(old_author_path, new_author_path)
+ except OSError as ex:
+ log.error("Rename author from: %s to %s: %s", old_author_path, new_author_path, ex)
+ log.error_or_exception(ex)
+ raise Exception(_("Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s",
+ src=old_author_path, dest=new_author_path, error=str(ex)))
return new_authordir
# Moves files in file storage during author/title rename, or from temp dir to file storage
diff --git a/cps/main.py b/cps/main.py
index 6afb18af..1b3b40b4 100644
--- a/cps/main.py
+++ b/cps/main.py
@@ -20,7 +20,6 @@ import sys
from . import create_app, limiter
from .jinjia import jinjia
-from .remotelogin import remotelogin
from flask import request
@@ -42,6 +41,7 @@ def main():
from .shelf import shelf
from .tasks_status import tasks
from .error_handler import init_errorhandler
+ from .remotelogin import remotelogin
try:
from .kobo import kobo, get_kobo_activated
from .kobo_auth import kobo_auth
diff --git a/cps/static/js/reading/epub.js b/cps/static/js/reading/epub.js
index 5047b1d3..a552da05 100644
--- a/cps/static/js/reading/epub.js
+++ b/cps/static/js/reading/epub.js
@@ -79,6 +79,6 @@ var reader;
}
// Default settings load
- const theme = localStorage.getItem("calibre.reader.theme") ?? Object.keys(themes)[0];
+ const theme = localStorage.getItem("calibre.reader.theme") ?? "lightTheme";
selectTheme(theme);
})();
diff --git a/cps/tasks/convert.py b/cps/tasks/convert.py
index e6af356f..3bef81a9 100644
--- a/cps/tasks/convert.py
+++ b/cps/tasks/convert.py
@@ -255,7 +255,7 @@ class TaskConvert(CalibreTask):
try:
# path_tmp_opf = self._embed_metadata()
if config.config_embed_metadata:
- quotes = [3, 5]
+ quotes = [5]
tmp_dir = get_temp_dir()
calibredb_binarypath = os.path.join(config.config_binariesdir, SUPPORTED_CALIBRE_BINARIES["calibredb"])
my_env = os.environ.copy()
diff --git a/cps/tasks/database.py b/cps/tasks/database.py
index e5aa26da..c9c30d43 100644
--- a/cps/tasks/database.py
+++ b/cps/tasks/database.py
@@ -16,11 +16,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-from urllib.request import urlopen
-
from flask_babel import lazy_gettext as N_
-from cps import config, logger
+from cps import config, logger, db, ub
from cps.services.worker import CalibreTask
@@ -28,18 +26,12 @@ class TaskReconnectDatabase(CalibreTask):
def __init__(self, task_message=N_('Reconnecting Calibre database')):
super(TaskReconnectDatabase, self).__init__(task_message)
self.log = logger.create()
- self.listen_address = config.get_config_ipaddress()
- self.listen_port = config.config_port
+ self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
def run(self, worker_thread):
- address = self.listen_address if self.listen_address else 'localhost'
- port = self.listen_port if self.listen_port else 8083
-
- try:
- urlopen('http://' + address + ':' + str(port) + '/reconnect')
- self._handleSuccess()
- except Exception as ex:
- self._handleError('Unable to reconnect Calibre database: ' + str(ex))
+ self.calibre_db.reconnect_db(config, ub.app_DB_path)
+ self.calibre_db.session.close()
+ self._handleSuccess()
@property
def name(self):
diff --git a/cps/tasks/thumbnail.py b/cps/tasks/thumbnail.py
index 2921ffc9..d2179dd9 100644
--- a/cps/tasks/thumbnail.py
+++ b/cps/tasks/thumbnail.py
@@ -70,7 +70,6 @@ class TaskGenerateCoverThumbnails(CalibreTask):
self.log = logger.create()
self.book_id = book_id
self.app_db_session = ub.get_new_session_instance()
- # self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
self.cache = fs.FileSystem()
self.resolutions = [
constants.COVER_THUMBNAIL_SMALL,
diff --git a/cps/web.py b/cps/web.py
index 7da22e3a..2519ebd5 100644
--- a/cps/web.py
+++ b/cps/web.py
@@ -89,21 +89,21 @@ except ImportError:
def add_security_headers(resp):
default_src = ([host.strip() for host in config.config_trustedhosts.split(',') if host] +
["'self'", "'unsafe-inline'", "'unsafe-eval'"])
- csp = "default-src " + ' '.join(default_src) + "; "
- csp += "font-src 'self' data:"
+ csp = "default-src " + ' '.join(default_src)
+ if request.endpoint == "web.read_book" and config.config_use_google_drive:
+ csp +=" blob: "
+ csp += "; font-src 'self' data:"
if request.endpoint == "web.read_book":
- csp += " blob:"
+ csp += " blob: "
csp += "; img-src 'self'"
if request.path.startswith("/author/") and config.config_use_goodreads:
csp += " images.gr-assets.com i.gr-assets.com s.gr-assets.com"
csp += " data:"
if request.endpoint == "edit-book.show_edit_book" or config.config_use_google_drive:
- csp += " *;"
- elif request.endpoint == "web.read_book":
- csp += " blob:; style-src-elem 'self' blob: 'unsafe-inline';"
- else:
- csp += ";"
- csp += " object-src 'none';"
+ csp += " *"
+ if request.endpoint == "web.read_book":
+ csp += " blob: ; style-src-elem 'self' blob: 'unsafe-inline'"
+ csp += "; object-src 'none';"
resp.headers['Content-Security-Policy'] = csp
resp.headers['X-Content-Type-Options'] = 'nosniff'
resp.headers['X-Frame-Options'] = 'SAMEORIGIN'
diff --git a/requirements.txt b/requirements.txt
index fd6a808c..460a7357 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,6 @@
-Werkzeug<3.0.0
APScheduler>=3.6.3,<3.11.0
Babel>=1.3,<3.0
Flask-Babel>=0.11.1,<4.1.0
-# Flask-Login>=0.3.2,<0.6.4
Flask-Principal>=0.3.2,<0.5.1
Flask>=1.0.2,<3.1.0
iso-639>=0.4.5,<0.5.0
@@ -17,8 +15,8 @@ lxml>=4.9.1,<5.3.0
flask-wtf>=0.14.2,<1.3.0
chardet>=3.0.0,<4.1.0
advocate>=1.0.0,<1.1.0
-Flask-Limiter>=2.3.0,<3.6.0
+Flask-Limiter>=2.3.0,<3.9.0
regex>=2022.3.2,<2024.6.25
bleach>=6.0.0,<6.2.0
python-magic>=0.4.27,<0.5.0
-flask-httpAuth>=4.4.0
+flask-httpAuth>=4.4.0,<5.0.0