diff --git a/LazyLibrarian.py b/LazyLibrarian.py index 3afd0982..9dc9aa9d 100644 --- a/LazyLibrarian.py +++ b/LazyLibrarian.py @@ -1,140 +1,140 @@ -#!/usr/bin/env python -# -*- coding: UTF-8 -*- - -# This file is part of Lazylibrarian. -# Lazylibrarian is free software':'you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# Lazylibrarian is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with Lazylibrarian. If not, see . - -# Purpose: -# Main file for starting LazyLibrarian - -import logging -import signal -import sys -import time - -import lazylibrarian -from lazylibrarian import startup, webStart -from lazylibrarian.formatter import thread_name -from lazylibrarian.cleanup import UNBUNDLER - -# The following should probably be made configurable at the settings level -# This fix is put in place for systems with broken SSL (like QNAP) -opt_out_of_certificate_verification = True -if opt_out_of_certificate_verification: - # noinspection PyBroadException - try: - import ssl - - # noinspection PyProtectedMember - ssl._create_default_https_context = ssl._create_unverified_context - except Exception: - pass - -# ==== end block (should be configurable at settings level) - -MIN_PYTHON_VERSION = (3, 7) - -if sys.version_info < MIN_PYTHON_VERSION: - sys.stderr.write("This version of Lazylibrarian requires Python %d.%d or later.\n" % MIN_PYTHON_VERSION) - exit(0) - - -def sig_shutdown(*args): - lazylibrarian.SIGNAL = 'shutdown' - - -def main(): - # rename this thread - thread_name("MAIN") - starter = startup.StartupLazyLibrarian() - # Set up a console-only logger until config is read - starter.init_loggers(console_only=True) - # Read command line and return options - options, configfile = starter.startup_parsecommandline(__file__, args=sys.argv[1:]) - # Load config.ini and initialize CONFIG and DIRS - starter.load_config(configfile) - # Read logging config and initialize loggers - starter.init_loggers(console_only=False) - # Run initialization that needs CONFIG to be loaded - starter.init_misc(lazylibrarian.config2.CONFIG) - starter.init_caches(lazylibrarian.config2.CONFIG) - starter.init_database() - starter.init_build_debug_header(online=True) - starter.init_build_lists(lazylibrarian.config2.CONFIG) - logger = logging.getLogger(__name__) - - version_file = starter.create_version_file('version.txt') - starter.init_version_checks(version_file) - - if lazylibrarian.DAEMON: - lazylibrarian.daemonize() - - # Try to start the server. - if options.port: - lazylibrarian.config2.CONFIG.set_int('HTTP_PORT', options.port) - logger.info('Starting LazyLibrarian on forced port: %s, webroot "%s"' % - (lazylibrarian.config2.CONFIG['HTTP_PORT'], lazylibrarian.config2.CONFIG['HTTP_ROOT'])) - else: - logger.info('Starting LazyLibrarian on port: %s, webroot "%s"' % - (lazylibrarian.config2.CONFIG['HTTP_PORT'], lazylibrarian.config2.CONFIG['HTTP_ROOT'])) - - webStart.initialize({ - 'http_port': lazylibrarian.config2.CONFIG.get_int('HTTP_PORT'), - 'http_host': lazylibrarian.config2.CONFIG['HTTP_HOST'], - 'http_root': lazylibrarian.config2.CONFIG['HTTP_ROOT'], - 'http_user': lazylibrarian.config2.CONFIG['HTTP_USER'], - 'http_pass': lazylibrarian.config2.CONFIG['HTTP_PASS'], - 'http_proxy': lazylibrarian.config2.CONFIG.get_bool('HTTP_PROXY'), - 'https_enabled': lazylibrarian.config2.CONFIG.get_bool('HTTPS_ENABLED'), - 'https_cert': lazylibrarian.config2.CONFIG['HTTPS_CERT'], - 'https_key': lazylibrarian.config2.CONFIG['HTTPS_KEY'], - 'opds_enabled': lazylibrarian.config2.CONFIG['OPDS_ENABLED'], - 'opds_authentication': lazylibrarian.config2.CONFIG.get_bool('OPDS_AUTHENTICATION'), - 'opds_username': lazylibrarian.config2.CONFIG['OPDS_USERNAME'], - 'opds_password': lazylibrarian.config2.CONFIG['OPDS_PASSWORD'], - 'authentication': lazylibrarian.config2.CONFIG['AUTH_TYPE'], - 'login_timeout': 43800, - }) - - if options.userid: - lazylibrarian.LOGINUSER = options.userid - else: - lazylibrarian.LOGINUSER = None - - if lazylibrarian.config2.CONFIG.get_bool('LAUNCH_BROWSER') and not options.nolaunch: - starter.launch_browser(lazylibrarian.config2.CONFIG['HTTP_HOST'], - lazylibrarian.config2.CONFIG['HTTP_PORT'], - lazylibrarian.config2.CONFIG['HTTP_ROOT']) - - starter.start_schedulers() - - signal.signal(signal.SIGTERM, sig_shutdown) - - while True: - if not lazylibrarian.SIGNAL: - try: - time.sleep(1) - except KeyboardInterrupt: - starter.shutdown(doquit=True) - else: - if lazylibrarian.SIGNAL == 'shutdown': - starter.shutdown(doquit=True) - elif lazylibrarian.SIGNAL == 'restart': - starter.shutdown(restart=True) - elif lazylibrarian.SIGNAL == 'update': - starter.shutdown(update=True) - lazylibrarian.SIGNAL = None - - -if __name__ == "__main__": - UNBUNDLER.prepare_module_unbundling() - main() +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# This file is part of Lazylibrarian. +# Lazylibrarian is free software':'you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Lazylibrarian is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Lazylibrarian. If not, see . + +# Purpose: +# Main file for starting LazyLibrarian + +import logging +import signal +import sys +import time + +import lazylibrarian +from lazylibrarian import startup, webStart +from lazylibrarian.formatter import thread_name +from lazylibrarian.cleanup import UNBUNDLER + +# The following should probably be made configurable at the settings level +# This fix is put in place for systems with broken SSL (like QNAP) +opt_out_of_certificate_verification = True +if opt_out_of_certificate_verification: + # noinspection PyBroadException + try: + import ssl + + # noinspection PyProtectedMember + ssl._create_default_https_context = ssl._create_unverified_context + except Exception: + pass + +# ==== end block (should be configurable at settings level) + +MIN_PYTHON_VERSION = (3, 7) + +if sys.version_info < MIN_PYTHON_VERSION: + sys.stderr.write("This version of Lazylibrarian requires Python %d.%d or later.\n" % MIN_PYTHON_VERSION) + exit(0) + + +def sig_shutdown(): + lazylibrarian.SIGNAL = 'shutdown' + + +def main(): + # rename this thread + thread_name("MAIN") + starter = startup.StartupLazyLibrarian() + # Set up a console-only logger until config is read + starter.init_loggers(console_only=True) + # Read command line and return options + options, configfile = starter.startup_parsecommandline(__file__, args=sys.argv[1:]) + # Load config.ini and initialize CONFIG and DIRS + starter.load_config(configfile) + # Read logging config and initialize loggers + starter.init_loggers(console_only=False) + # Run initialization that needs CONFIG to be loaded + starter.init_misc(lazylibrarian.config2.CONFIG) + starter.init_caches(lazylibrarian.config2.CONFIG) + starter.init_database() + starter.init_build_debug_header(online=True) + starter.init_build_lists(lazylibrarian.config2.CONFIG) + logger = logging.getLogger(__name__) + + version_file = starter.create_version_file('version.txt') + starter.init_version_checks(version_file) + + if lazylibrarian.DAEMON: + lazylibrarian.daemonize() + + # Try to start the server. + if options.port: + lazylibrarian.config2.CONFIG.set_int('HTTP_PORT', options.port) + logger.info('Starting LazyLibrarian on forced port: %s, webroot "%s"' % + (lazylibrarian.config2.CONFIG['HTTP_PORT'], lazylibrarian.config2.CONFIG['HTTP_ROOT'])) + else: + logger.info('Starting LazyLibrarian on port: %s, webroot "%s"' % + (lazylibrarian.config2.CONFIG['HTTP_PORT'], lazylibrarian.config2.CONFIG['HTTP_ROOT'])) + + webStart.initialize({ + 'http_port': lazylibrarian.config2.CONFIG.get_int('HTTP_PORT'), + 'http_host': lazylibrarian.config2.CONFIG['HTTP_HOST'], + 'http_root': lazylibrarian.config2.CONFIG['HTTP_ROOT'], + 'http_user': lazylibrarian.config2.CONFIG['HTTP_USER'], + 'http_pass': lazylibrarian.config2.CONFIG['HTTP_PASS'], + 'http_proxy': lazylibrarian.config2.CONFIG.get_bool('HTTP_PROXY'), + 'https_enabled': lazylibrarian.config2.CONFIG.get_bool('HTTPS_ENABLED'), + 'https_cert': lazylibrarian.config2.CONFIG['HTTPS_CERT'], + 'https_key': lazylibrarian.config2.CONFIG['HTTPS_KEY'], + 'opds_enabled': lazylibrarian.config2.CONFIG['OPDS_ENABLED'], + 'opds_authentication': lazylibrarian.config2.CONFIG.get_bool('OPDS_AUTHENTICATION'), + 'opds_username': lazylibrarian.config2.CONFIG['OPDS_USERNAME'], + 'opds_password': lazylibrarian.config2.CONFIG['OPDS_PASSWORD'], + 'authentication': lazylibrarian.config2.CONFIG['AUTH_TYPE'], + 'login_timeout': 43800, + }) + + if options.userid: + lazylibrarian.LOGINUSER = options.userid + else: + lazylibrarian.LOGINUSER = None + + if lazylibrarian.config2.CONFIG.get_bool('LAUNCH_BROWSER') and not options.nolaunch: + starter.launch_browser(lazylibrarian.config2.CONFIG['HTTP_HOST'], + lazylibrarian.config2.CONFIG['HTTP_PORT'], + lazylibrarian.config2.CONFIG['HTTP_ROOT']) + + starter.start_schedulers() + + signal.signal(signal.SIGTERM, sig_shutdown) + + while True: + if not lazylibrarian.SIGNAL: + try: + time.sleep(1) + except KeyboardInterrupt: + starter.shutdown(doquit=True) + else: + if lazylibrarian.SIGNAL == 'shutdown': + starter.shutdown(doquit=True) + elif lazylibrarian.SIGNAL == 'restart': + starter.shutdown(restart=True) + elif lazylibrarian.SIGNAL == 'update': + starter.shutdown(update=True) + lazylibrarian.SIGNAL = None + + +if __name__ == "__main__": + UNBUNDLER.prepare_module_unbundling() + main() diff --git a/example.dicts.json b/example.dicts.json new file mode 100644 index 00000000..a48b648b --- /dev/null +++ b/example.dicts.json @@ -0,0 +1,37 @@ +{ + "filename_dict": { + "<": "", + ">": "", + "...": "", + " & ": " ", + " = ": " ", + "?": "", + "$": "s", + "|": "", + " + ": " ", + "\"": "", + ",": "", + "*": "", + ":": "", + ";": "", + "'": "", + "//": "/", + "\\\\": "\\" + }, + "umlaut_dict": { + "\u00e4": "ae", + "\u00f6": "oe", + "\u00fc": "ue", + "\u00c4": "Ae", + "\u00d6": "Oe", + "\u00dc": "Ue", + "\u00df": "ss" + }, + "apostrophe_dict": { + "`": "'", + "\u2018": "'", + "\u2019": "'", + "\u201c": "\"", + "\u201d": "\"" + } +} diff --git a/lazylibrarian/filesystem.py b/lazylibrarian/filesystem.py index 5104f4ed..947ca3d7 100644 --- a/lazylibrarian/filesystem.py +++ b/lazylibrarian/filesystem.py @@ -15,7 +15,7 @@ from datetime import datetime from typing import Optional from lazylibrarian.configtypes import ConfigDict -from lazylibrarian.formatter import make_bytestr, make_unicode, unaccented, replace_all, namedic, get_list +from lazylibrarian.formatter import make_bytestr, make_unicode, unaccented, replace_all, get_list class DirectoryHolder: @@ -440,7 +440,7 @@ def safe_move(src, dst, action='move'): drive, path = os.path.splitdrive(dst) logger.debug("drive=[%s] path=[%s]" % (drive, path)) # strip some characters windows can't handle - newpath = replace_all(path, namedic) + newpath = replace_all(path, lazylibrarian.DICTS.get('filename_dict', {})) # windows filenames can't end in space or dot while newpath and newpath[-1] in '. ': newpath = newpath[:-1] diff --git a/lazylibrarian/startup.py b/lazylibrarian/startup.py index 06ce292c..a1b63250 100644 --- a/lazylibrarian/startup.py +++ b/lazylibrarian/startup.py @@ -308,6 +308,7 @@ class StartupLazyLibrarian: def init_build_lists(self, config: ConfigDict): lazylibrarian.GRGENRES = self.build_genres() + lazylibrarian.DICTS = self.build_dicts() lazylibrarian.MONTHNAMES = self.build_monthtable(config) lazylibrarian.NEWUSER_MSG = self.build_logintemplate() lazylibrarian.NEWFILE_MSG = self.build_filetemplate() @@ -419,6 +420,25 @@ class StartupLazyLibrarian: self.logger.error('No valid genres.json file found') return {"genreLimit": 4, "genreUsers": 10, "genreExclude": [], "genreExcludeParts": [], "genreReplace": {}} + def build_dicts(self): + for json_file in [os.path.join(DIRS.DATADIR, 'dicts.json'), + os.path.join(DIRS.PROG_DIR, 'example.dicts.json')]: + if path_isfile(json_file): + try: + with open(syspath(json_file), 'r', encoding='utf-8') as json_data: + res = json.load(json_data) + self.logger.info("Loaded dicts from %s" % json_file) + return res + except Exception as e: + self.logger.error('Failed to load %s, %s %s' % (json_file, type(e).__name__, str(e))) + self.logger.error('No valid dicts.json file found') + return {"filename_dict": {'<': '', '>': '', '...': '', ' & ': ' ', ' = ': ' ', '?': '', '$': 's', '|': '', ' + ': ' ', + '"': '', ',': '', '*': '', ':': '', ';': '', '\'': '', '//': '/', '\\\\': '\\'}, + "umlaut_dict": {u'\xe4': 'ae', u'\xf6': 'oe', u'\xfc': 'ue', u'\xc4': 'Ae', u'\xd6': 'Oe', u'\xdc': 'Ue', u'\xdf': 'ss'}, + "apostrophe_dict": {u'\u0060': "'", u'\u2018': u"'", u'\u2019': u"'", u'\u201c': u'"', u'\u201d': u'"'} + } + + def build_monthtable(self, config: ConfigDict): table = [] json_file = os.path.join(DIRS.DATADIR, 'monthnames.json')