mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 15:23:02 +00:00 
			
		
		
		
	Improved whitespace removal
Testresults
This commit is contained in:
		
							
								
								
									
										22
									
								
								cps/admin.py
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								cps/admin.py
									
									
									
									
									
								
							| @@ -54,6 +54,7 @@ from .services.worker import WorkerThread | |||||||
| from .usermanagement import user_login_required | from .usermanagement import user_login_required | ||||||
| from .babel import get_available_translations, get_available_locale, get_user_locale_language | from .babel import get_available_translations, get_available_locale, get_user_locale_language | ||||||
| from . import debug_info | from . import debug_info | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
|  |  | ||||||
| @@ -463,9 +464,9 @@ def edit_list_user(param): | |||||||
|                 if 'value[]' in vals: |                 if 'value[]' in vals: | ||||||
|                     setattr(user, param, prepare_tags(user, vals['action'][0], param, vals['value[]'])) |                     setattr(user, param, prepare_tags(user, vals['action'][0], param, vals['value[]'])) | ||||||
|                 else: |                 else: | ||||||
|                     setattr(user, param, vals['value'].strip()) |                     setattr(user, param, strip_whitespaces(vals['value'])) | ||||||
|             else: |             else: | ||||||
|                 vals['value'] = vals['value'].strip() |                 vals['value'] = strip_whitespaces(vals['value']) | ||||||
|                 if param == 'name': |                 if param == 'name': | ||||||
|                     if user.name == "Guest": |                     if user.name == "Guest": | ||||||
|                         raise Exception(_("Guest Name can't be changed")) |                         raise Exception(_("Guest Name can't be changed")) | ||||||
| @@ -690,7 +691,7 @@ def delete_domain(): | |||||||
| def list_domain(allow): | def list_domain(allow): | ||||||
|     answer = ub.session.query(ub.Registration).filter(ub.Registration.allow == allow).all() |     answer = ub.session.query(ub.Registration).filter(ub.Registration.allow == allow).all() | ||||||
|     json_dumps = json.dumps([{"domain": r.domain.replace('%', '*').replace('_', '?'), "id": r.id} for r in answer]) |     json_dumps = json.dumps([{"domain": r.domain.replace('%', '*').replace('_', '?'), "id": r.id} for r in answer]) | ||||||
|     js = json.dumps(json_dumps.replace('"', "'")).lstrip('"').strip('"') |     js = json.dumps(json_dumps.replace('"', "'")).strip('"') | ||||||
|     response = make_response(js.replace("'", '"')) |     response = make_response(js.replace("'", '"')) | ||||||
|     response.headers["Content-Type"] = "application/json; charset=utf-8" |     response.headers["Content-Type"] = "application/json; charset=utf-8" | ||||||
|     return response |     return response | ||||||
| @@ -1100,7 +1101,7 @@ def _config_checkbox_int(to_save, x): | |||||||
|  |  | ||||||
|  |  | ||||||
| def _config_string(to_save, x): | def _config_string(to_save, x): | ||||||
|     return config.set_from_dictionary(to_save, x, lambda y: y.strip().strip(u'\u200B\u200C\u200D\ufeff') if y else y) |     return config.set_from_dictionary(to_save, x, lambda y: strip_whitespaces(y) if y else y) | ||||||
|  |  | ||||||
|  |  | ||||||
| def _configuration_gdrive_helper(to_save): | def _configuration_gdrive_helper(to_save): | ||||||
| @@ -1311,9 +1312,9 @@ def update_mailsettings(): | |||||||
|         if to_save.get("mail_password_e", ""): |         if to_save.get("mail_password_e", ""): | ||||||
|             _config_string(to_save, "mail_password_e") |             _config_string(to_save, "mail_password_e") | ||||||
|         _config_int(to_save, "mail_size", lambda y: int(y) * 1024 * 1024) |         _config_int(to_save, "mail_size", lambda y: int(y) * 1024 * 1024) | ||||||
|         config.mail_server = to_save.get('mail_server', "").strip() |         config.mail_server = strip_whitespaces(to_save.get('mail_server', "")) | ||||||
|         config.mail_from = to_save.get('mail_from', "").strip() |         config.mail_from = strip_whitespaces(to_save.get('mail_from', "")) | ||||||
|         config.mail_login = to_save.get('mail_login', "").strip() |         config.mail_login = strip_whitespaces(to_save.get('mail_login', "")) | ||||||
|     try: |     try: | ||||||
|         config.save() |         config.save() | ||||||
|     except (OperationalError, InvalidRequestError) as e: |     except (OperationalError, InvalidRequestError) as e: | ||||||
| @@ -1678,10 +1679,10 @@ def cancel_task(): | |||||||
| def _db_simulate_change(): | def _db_simulate_change(): | ||||||
|     param = request.form.to_dict() |     param = request.form.to_dict() | ||||||
|     to_save = dict() |     to_save = dict() | ||||||
|     to_save['config_calibre_dir'] = re.sub(r'[\\/]metadata\.db$', |     to_save['config_calibre_dir'] = strip_whitespaces(re.sub(r'[\\/]metadata\.db$', | ||||||
|                                            '', |                                            '', | ||||||
|                                            param['config_calibre_dir'], |                                            param['config_calibre_dir'], | ||||||
|                                            flags=re.IGNORECASE).strip() |                                            flags=re.IGNORECASE)) | ||||||
|     db_valid, db_change = calibre_db.check_valid_db(to_save["config_calibre_dir"], |     db_valid, db_change = calibre_db.check_valid_db(to_save["config_calibre_dir"], | ||||||
|                                                     ub.app_DB_path, |                                                     ub.app_DB_path, | ||||||
|                                                     config.config_calibre_uuid) |                                                     config.config_calibre_uuid) | ||||||
| @@ -1775,9 +1776,8 @@ def _configuration_update_helper(): | |||||||
|  |  | ||||||
|         if "config_upload_formats" in to_save: |         if "config_upload_formats" in to_save: | ||||||
|             to_save["config_upload_formats"] = ','.join( |             to_save["config_upload_formats"] = ','.join( | ||||||
|                 helper.uniq([x.lstrip().rstrip().lower() for x in to_save["config_upload_formats"].split(',')])) |                 helper.uniq([x.strip().lower() for x in to_save["config_upload_formats"].split(',')])) | ||||||
|             _config_string(to_save, "config_upload_formats") |             _config_string(to_save, "config_upload_formats") | ||||||
|             # constants.EXTENSIONS_UPLOAD = config.config_upload_formats.split(',') |  | ||||||
|  |  | ||||||
|         _config_string(to_save, "config_calibre") |         _config_string(to_save, "config_calibre") | ||||||
|         _config_string(to_save, "config_binariesdir") |         _config_string(to_save, "config_binariesdir") | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ except ImportError: | |||||||
|  |  | ||||||
| from . import constants, logger | from . import constants, logger | ||||||
| from .subproc_wrapper import process_wait | from .subproc_wrapper import process_wait | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
| _Base = declarative_base() | _Base = declarative_base() | ||||||
| @@ -288,19 +288,19 @@ class ConfigSQL(object): | |||||||
|  |  | ||||||
|     def list_denied_tags(self): |     def list_denied_tags(self): | ||||||
|         mct = self.config_denied_tags or "" |         mct = self.config_denied_tags or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def list_allowed_tags(self): |     def list_allowed_tags(self): | ||||||
|         mct = self.config_allowed_tags or "" |         mct = self.config_allowed_tags or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def list_denied_column_values(self): |     def list_denied_column_values(self): | ||||||
|         mct = self.config_denied_column_value or "" |         mct = self.config_denied_column_value or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def list_allowed_column_values(self): |     def list_allowed_column_values(self): | ||||||
|         mct = self.config_allowed_column_value or "" |         mct = self.config_allowed_column_value or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def get_log_level(self): |     def get_log_level(self): | ||||||
|         return logger.get_level_name(self.config_log_level) |         return logger.get_level_name(self.config_log_level) | ||||||
| @@ -372,7 +372,7 @@ class ConfigSQL(object): | |||||||
|             db_file = os.path.join(self.config_calibre_dir, 'metadata.db') |             db_file = os.path.join(self.config_calibre_dir, 'metadata.db') | ||||||
|             have_metadata_db = os.path.isfile(db_file) |             have_metadata_db = os.path.isfile(db_file) | ||||||
|         self.db_configured = have_metadata_db |         self.db_configured = have_metadata_db | ||||||
|         # constants.EXTENSIONS_UPLOAD = [x.lstrip().rstrip().lower() for x in self.config_upload_formats.split(',')] |          | ||||||
|         from . import cli_param |         from . import cli_param | ||||||
|         if os.environ.get('FLASK_DEBUG'): |         if os.environ.get('FLASK_DEBUG'): | ||||||
|             logfile = logger.setup(logger.LOG_TO_STDOUT, logger.logging.DEBUG) |             logfile = logger.setup(logger.LOG_TO_STDOUT, logger.logging.DEBUG) | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								cps/db.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								cps/db.py
									
									
									
									
									
								
							| @@ -48,7 +48,7 @@ from flask import flash | |||||||
|  |  | ||||||
| from . import logger, ub, isoLanguages | from . import logger, ub, isoLanguages | ||||||
| from .pagination import Pagination | from .pagination import Pagination | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
|  |  | ||||||
| @@ -875,10 +875,11 @@ class CalibreDB: | |||||||
|             authors_ordered = list() |             authors_ordered = list() | ||||||
|             # error = False |             # error = False | ||||||
|             for auth in sort_authors: |             for auth in sort_authors: | ||||||
|                 results = self.session.query(Authors).filter(Authors.sort == auth.lstrip().strip()).all() |                 auth = strip_whitespaces(auth) | ||||||
|  |                 results = self.session.query(Authors).filter(Authors.sort == auth).all() | ||||||
|                 # ToDo: How to handle not found author name |                 # ToDo: How to handle not found author name | ||||||
|                 if not len(results): |                 if not len(results): | ||||||
|                     log.error("Author {} not found to display name in right order".format(auth.strip())) |                     log.error("Author {} not found to display name in right order".format(auth)) | ||||||
|                     # error = True |                     # error = True | ||||||
|                     break |                     break | ||||||
|                 for r in results: |                 for r in results: | ||||||
| @@ -918,7 +919,7 @@ class CalibreDB: | |||||||
|             .filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first() |             .filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first() | ||||||
|  |  | ||||||
|     def search_query(self, term, config, *join): |     def search_query(self, term, config, *join): | ||||||
|         term.strip().lower() |         strip_whitespaces(term).lower() | ||||||
|         self.session.connection().connection.connection.create_function("lower", 1, lcase) |         self.session.connection().connection.connection.create_function("lower", 1, lcase) | ||||||
|         q = list() |         q = list() | ||||||
|         author_terms = re.split("[, ]+", term) |         author_terms = re.split("[, ]+", term) | ||||||
| @@ -1026,7 +1027,7 @@ class CalibreDB: | |||||||
|             if match: |             if match: | ||||||
|                 prep = match.group(1) |                 prep = match.group(1) | ||||||
|                 title = title[len(prep):] + ', ' + prep |                 title = title[len(prep):] + ', ' + prep | ||||||
|             return title.strip() |             return strip_whitespaces(title) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             # sqlalchemy <1.4.24 and sqlalchemy 2.0 |             # sqlalchemy <1.4.24 and sqlalchemy 2.0 | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ from .kobo_sync_status import change_archived_books | |||||||
| from .redirect import get_redirect_location | from .redirect import get_redirect_location | ||||||
| from .file_helper import validate_mime_type | from .file_helper import validate_mime_type | ||||||
| from .usermanagement import user_login_required, login_required_if_no_ano | from .usermanagement import user_login_required, login_required_if_no_ano | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| editbook = Blueprint('edit-book', __name__) | editbook = Blueprint('edit-book', __name__) | ||||||
| log = logger.create() | log = logger.create() | ||||||
| @@ -979,7 +979,7 @@ def render_edit_book(book_id): | |||||||
|  |  | ||||||
| def edit_book_ratings(to_save, book): | def edit_book_ratings(to_save, book): | ||||||
|     changed = False |     changed = False | ||||||
|     if to_save.get("rating", "").strip(): |     if strip_whitespaces(to_save.get("rating", "")): | ||||||
|         old_rating = False |         old_rating = False | ||||||
|         if len(book.ratings) > 0: |         if len(book.ratings) > 0: | ||||||
|             old_rating = book.ratings[0].rating |             old_rating = book.ratings[0].rating | ||||||
| @@ -1003,14 +1003,14 @@ def edit_book_ratings(to_save, book): | |||||||
|  |  | ||||||
| def edit_book_tags(tags, book): | def edit_book_tags(tags, book): | ||||||
|     input_tags = tags.split(',') |     input_tags = tags.split(',') | ||||||
|     input_tags = list(map(lambda it: it.strip(), input_tags)) |     input_tags = list(map(lambda it: strip_whitespaces(it), input_tags)) | ||||||
|     # Remove duplicates |     # Remove duplicates | ||||||
|     input_tags = helper.uniq(input_tags) |     input_tags = helper.uniq(input_tags) | ||||||
|     return modify_database_object(input_tags, book.tags, db.Tags, calibre_db.session, 'tags') |     return modify_database_object(input_tags, book.tags, db.Tags, calibre_db.session, 'tags') | ||||||
|  |  | ||||||
|  |  | ||||||
| def edit_book_series(series, book): | def edit_book_series(series, book): | ||||||
|     input_series = [series.strip()] |     input_series = [strip_whitespaces(series)] | ||||||
|     input_series = [x for x in input_series if x != ''] |     input_series = [x for x in input_series if x != ''] | ||||||
|     return modify_database_object(input_series, book.series, db.Series, calibre_db.session, 'series') |     return modify_database_object(input_series, book.series, db.Series, calibre_db.session, 'series') | ||||||
|  |  | ||||||
| @@ -1072,7 +1072,7 @@ def edit_book_languages(languages, book, upload_mode=False, invalid=None): | |||||||
| def edit_book_publisher(publishers, book): | def edit_book_publisher(publishers, book): | ||||||
|     changed = False |     changed = False | ||||||
|     if publishers: |     if publishers: | ||||||
|         publisher = publishers.rstrip().strip() |         publisher = strip_whitespaces(publishers) | ||||||
|         if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name): |         if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name): | ||||||
|             changed |= modify_database_object([publisher], book.publishers, db.Publishers, calibre_db.session, |             changed |= modify_database_object([publisher], book.publishers, db.Publishers, calibre_db.session, | ||||||
|                                               'publisher') |                                               'publisher') | ||||||
| @@ -1119,7 +1119,7 @@ def edit_cc_data_string(book, c, to_save, cc_db_value, cc_string): | |||||||
|     changed = False |     changed = False | ||||||
|     if c.datatype == 'rating': |     if c.datatype == 'rating': | ||||||
|         to_save[cc_string] = str(int(float(to_save[cc_string]) * 2)) |         to_save[cc_string] = str(int(float(to_save[cc_string]) * 2)) | ||||||
|     if to_save[cc_string].strip() != cc_db_value: |     if strip_whitespaces(to_save[cc_string]) != cc_db_value: | ||||||
|         if cc_db_value is not None: |         if cc_db_value is not None: | ||||||
|             # remove old cc_val |             # remove old cc_val | ||||||
|             del_cc = getattr(book, cc_string)[0] |             del_cc = getattr(book, cc_string)[0] | ||||||
| @@ -1129,15 +1129,15 @@ def edit_cc_data_string(book, c, to_save, cc_db_value, cc_string): | |||||||
|                 changed = True |                 changed = True | ||||||
|         cc_class = db.cc_classes[c.id] |         cc_class = db.cc_classes[c.id] | ||||||
|         new_cc = calibre_db.session.query(cc_class).filter( |         new_cc = calibre_db.session.query(cc_class).filter( | ||||||
|             cc_class.value == to_save[cc_string].strip()).first() |             cc_class.value == strip_whitespaces(to_save[cc_string])).first() | ||||||
|         # if no cc val is found add it |         # if no cc val is found add it | ||||||
|         if new_cc is None: |         if new_cc is None: | ||||||
|             new_cc = cc_class(value=to_save[cc_string].strip()) |             new_cc = cc_class(value=strip_whitespaces(to_save[cc_string])) | ||||||
|             calibre_db.session.add(new_cc) |             calibre_db.session.add(new_cc) | ||||||
|             changed = True |             changed = True | ||||||
|             calibre_db.session.flush() |             calibre_db.session.flush() | ||||||
|             new_cc = calibre_db.session.query(cc_class).filter( |             new_cc = calibre_db.session.query(cc_class).filter( | ||||||
|                 cc_class.value == to_save[cc_string].strip()).first() |                 cc_class.value == strip_whitespaces(to_save[cc_string])).first() | ||||||
|         # add cc value to book |         # add cc value to book | ||||||
|         getattr(book, cc_string).append(new_cc) |         getattr(book, cc_string).append(new_cc) | ||||||
|     return changed, to_save |     return changed, to_save | ||||||
| @@ -1165,7 +1165,7 @@ def edit_cc_data(book_id, book, to_save, cc): | |||||||
|                 cc_db_value = getattr(book, cc_string)[0].value |                 cc_db_value = getattr(book, cc_string)[0].value | ||||||
|             else: |             else: | ||||||
|                 cc_db_value = None |                 cc_db_value = None | ||||||
|             if to_save[cc_string].strip(): |             if strip_whitespaces(to_save[cc_string]): | ||||||
|                 if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]: |                 if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]: | ||||||
|                     change, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string) |                     change, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string) | ||||||
|                 else: |                 else: | ||||||
| @@ -1181,7 +1181,7 @@ def edit_cc_data(book_id, book, to_save, cc): | |||||||
|                         changed = True |                         changed = True | ||||||
|         else: |         else: | ||||||
|             input_tags = to_save[cc_string].split(',') |             input_tags = to_save[cc_string].split(',') | ||||||
|             input_tags = list(map(lambda it: it.strip(), input_tags)) |             input_tags = list(map(lambda it: strip_whitespaces(it), input_tags)) | ||||||
|             changed |= modify_database_object(input_tags, |             changed |= modify_database_object(input_tags, | ||||||
|                                               getattr(book, cc_string), |                                               getattr(book, cc_string), | ||||||
|                                               db.cc_classes[c.id], |                                               db.cc_classes[c.id], | ||||||
| @@ -1284,7 +1284,7 @@ def upload_cover(cover_request, book): | |||||||
|  |  | ||||||
| def handle_title_on_edit(book, book_title): | def handle_title_on_edit(book, book_title): | ||||||
|     # handle book title |     # handle book title | ||||||
|     book_title = book_title.rstrip().strip() |     book_title = strip_whitespaces(book_title) | ||||||
|     if book.title != book_title: |     if book.title != book_title: | ||||||
|         if book_title == '': |         if book_title == '': | ||||||
|             book_title = _(u'Unknown') |             book_title = _(u'Unknown') | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ from . import config, logger | |||||||
| from .helper import split_authors | from .helper import split_authors | ||||||
| from .epub_helper import get_content_opf, default_ns | from .epub_helper import get_content_opf, default_ns | ||||||
| from .constants import BookMeta | from .constants import BookMeta | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
|  |  | ||||||
| @@ -90,7 +91,7 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): | |||||||
|             elif s == 'date': |             elif s == 'date': | ||||||
|                 epub_metadata[s] = tmp[0][:10] |                 epub_metadata[s] = tmp[0][:10] | ||||||
|             else: |             else: | ||||||
|                 epub_metadata[s] = tmp[0].strip() |                 epub_metadata[s] = strip_whitespaces(tmp[0]) | ||||||
|         else: |         else: | ||||||
|             epub_metadata[s] = 'Unknown' |             epub_metadata[s] = 'Unknown' | ||||||
|  |  | ||||||
|   | |||||||
| @@ -52,6 +52,7 @@ except ImportError: | |||||||
|     UnacceptableAddressException = MissingSchema = BaseException |     UnacceptableAddressException = MissingSchema = BaseException | ||||||
|  |  | ||||||
| from . import calibre_db, cli_param | from . import calibre_db, cli_param | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
| from .tasks.convert import TaskConvert | from .tasks.convert import TaskConvert | ||||||
| from . import logger, config, db, ub, fs | from . import logger, config, db, ub, fs | ||||||
| from . import gdriveutils as gd | from . import gdriveutils as gd | ||||||
| @@ -118,7 +119,7 @@ def convert_book_format(book_id, calibre_path, old_book_format, new_book_format, | |||||||
| # Texts are not lazy translated as they are supposed to get send out as is | # Texts are not lazy translated as they are supposed to get send out as is | ||||||
| def send_test_mail(ereader_mail, user_name): | def send_test_mail(ereader_mail, user_name): | ||||||
|     for email in ereader_mail.split(','): |     for email in ereader_mail.split(','): | ||||||
|         email = email.strip() |         email = strip_whitespaces(email) | ||||||
|         WorkerThread.add(user_name, TaskEmail(_('Calibre-Web Test Email'), None, None, |         WorkerThread.add(user_name, TaskEmail(_('Calibre-Web Test Email'), None, None, | ||||||
|                          config.get_mail_settings(), email, N_("Test Email"), |                          config.get_mail_settings(), email, N_("Test Email"), | ||||||
|                                               _('This Email has been sent via Calibre-Web.'))) |                                               _('This Email has been sent via Calibre-Web.'))) | ||||||
| @@ -228,7 +229,7 @@ def send_mail(book_id, book_format, convert, ereader_mail, calibrepath, user_id) | |||||||
|             link = '<a href="{}">{}</a>'.format(url_for('web.show_book', book_id=book_id), escape(book.title)) |             link = '<a href="{}">{}</a>'.format(url_for('web.show_book', book_id=book_id), escape(book.title)) | ||||||
|             email_text = N_("%(book)s send to eReader", book=link) |             email_text = N_("%(book)s send to eReader", book=link) | ||||||
|             for email in ereader_mail.split(','): |             for email in ereader_mail.split(','): | ||||||
|                 email = email.strip() |                 email = strip_whitespaces(email) | ||||||
|                 WorkerThread.add(user_id, TaskEmail(_("Send to eReader"), book.path, converted_file_name, |                 WorkerThread.add(user_id, TaskEmail(_("Send to eReader"), book.path, converted_file_name, | ||||||
|                                  config.get_mail_settings(), email, |                                  config.get_mail_settings(), email, | ||||||
|                                  email_text, _('This Email has been sent via Calibre-Web.'), book.id)) |                                  email_text, _('This Email has been sent via Calibre-Web.'), book.id)) | ||||||
| @@ -252,7 +253,7 @@ def get_valid_filename(value, replace_whitespace=True, chars=128): | |||||||
|         # pipe has to be replaced with comma |         # pipe has to be replaced with comma | ||||||
|         value = re.sub(r'[|]+', ',', value, flags=re.U) |         value = re.sub(r'[|]+', ',', value, flags=re.U) | ||||||
|  |  | ||||||
|     value = value.encode('utf-8')[:chars].decode('utf-8', errors='ignore').strip() |     value = strip_whitespaces(value.encode('utf-8')[:chars].decode('utf-8', errors='ignore')) | ||||||
|  |  | ||||||
|     if not value: |     if not value: | ||||||
|         raise ValueError("Filename cannot be empty") |         raise ValueError("Filename cannot be empty") | ||||||
| @@ -267,11 +268,11 @@ def split_authors(values): | |||||||
|             commas = author.count(',') |             commas = author.count(',') | ||||||
|             if commas == 1: |             if commas == 1: | ||||||
|                 author_split = author.split(',') |                 author_split = author.split(',') | ||||||
|                 authors_list.append(author_split[1].strip() + ' ' + author_split[0].strip()) |                 authors_list.append(strip_whitespaces(author_split[1]) + ' ' + strip_whitespaces(author_split[0])) | ||||||
|             elif commas > 1: |             elif commas > 1: | ||||||
|                 authors_list.extend([x.strip() for x in author.split(',')]) |                 authors_list.extend([strip_whitespaces(x) for x in author.split(',')]) | ||||||
|             else: |             else: | ||||||
|                 authors_list.append(author.strip()) |                 authors_list.append(strip_whitespaces(author)) | ||||||
|     return authors_list |     return authors_list | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -661,7 +662,7 @@ def check_email(email): | |||||||
|  |  | ||||||
|  |  | ||||||
| def check_username(username): | def check_username(username): | ||||||
|     username = username.strip() |     username = strip_whitespaces(username) | ||||||
|     if ub.session.query(ub.User).filter(func.lower(ub.User.name) == username.lower()).scalar(): |     if ub.session.query(ub.User).filter(func.lower(ub.User.name) == username.lower()).scalar(): | ||||||
|         log.error("This username is already taken") |         log.error("This username is already taken") | ||||||
|         raise Exception(_("This username is already taken")) |         raise Exception(_("This username is already taken")) | ||||||
| @@ -670,7 +671,7 @@ def check_username(username): | |||||||
|  |  | ||||||
| def valid_email(emails): | def valid_email(emails): | ||||||
|     for email in emails.split(','): |     for email in emails.split(','): | ||||||
| 	    email = email.strip() |         email = strip_whitespaces(email) | ||||||
|         # if email is not deleted |         # if email is not deleted | ||||||
|         if email: |         if email: | ||||||
|             # Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation |             # Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation | ||||||
|   | |||||||
| @@ -24,9 +24,9 @@ from flask_babel import format_date | |||||||
| from flask_babel import gettext as _ | from flask_babel import gettext as _ | ||||||
| from sqlalchemy.sql.expression import func, not_, and_, or_, text, true | from sqlalchemy.sql.expression import func, not_, and_, or_, text, true | ||||||
| from sqlalchemy.sql.functions import coalesce | from sqlalchemy.sql.functions import coalesce | ||||||
| from sqlalchemy import exists |  | ||||||
|  |  | ||||||
| from . import logger, db, calibre_db, config, ub | from . import logger, db, calibre_db, config, ub | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
| from .usermanagement import login_required_if_no_ano | from .usermanagement import login_required_if_no_ano | ||||||
| from .render_template import render_title_template | from .render_template import render_title_template | ||||||
| from .pagination import Pagination | from .pagination import Pagination | ||||||
| @@ -267,11 +267,11 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): | |||||||
|     description = term.get("comment") |     description = term.get("comment") | ||||||
|     read_status = term.get("read_status") |     read_status = term.get("read_status") | ||||||
|     if author_name: |     if author_name: | ||||||
|         author_name = author_name.strip().lower().replace(',', '|') |         author_name = strip_whitespaces(author_name).lower().replace(',', '|') | ||||||
|     if book_title: |     if book_title: | ||||||
|         book_title = book_title.strip().lower() |         book_title = strip_whitespaces(book_title).lower() | ||||||
|     if publisher: |     if publisher: | ||||||
|         publisher = publisher.strip().lower() |         publisher = strip_whitespaces(publisher).lower() | ||||||
|  |  | ||||||
|     search_term = [] |     search_term = [] | ||||||
|     cc_present = False |     cc_present = False | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								cps/string_helper.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								cps/string_helper.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | #  This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web) | ||||||
|  | #    Copyright (C) 2024 OzzieIsaacs | ||||||
|  | # | ||||||
|  | #  This program 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. | ||||||
|  | # | ||||||
|  | #  This program 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 this program. If not, see <http://www.gnu.org/licenses/>. | ||||||
|  | import re | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def strip_whitespaces(text): | ||||||
|  |     return re.sub("(^[\s\u200B-\u200D\ufeff]+)|([\s\u200B-\u200D\ufeff]+$)","", text) | ||||||
|  |  | ||||||
| @@ -39,6 +39,7 @@ from cps.file_helper import get_temp_dir | |||||||
| from cps.tasks.mail import TaskEmail | from cps.tasks.mail import TaskEmail | ||||||
| from cps import gdriveutils, helper | from cps import gdriveutils, helper | ||||||
| from cps.constants import SUPPORTED_CALIBRE_BINARIES | from cps.constants import SUPPORTED_CALIBRE_BINARIES | ||||||
|  | from cps.string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
|  |  | ||||||
| @@ -107,7 +108,7 @@ class TaskConvert(CalibreTask): | |||||||
|                 try: |                 try: | ||||||
|                     EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))                     |                     EmailText = N_(u"%(book)s send to E-Reader", book=escape(self.title))                     | ||||||
|                     for email in self.ereader_mail.split(','): |                     for email in self.ereader_mail.split(','): | ||||||
|                         email = email.strip() |                         email = strip_whitespaces(email) | ||||||
|                         worker_thread.add(self.user, TaskEmail(self.settings['subject'], |                         worker_thread.add(self.user, TaskEmail(self.settings['subject'], | ||||||
|                                                                self.results["path"], |                                                                self.results["path"], | ||||||
|                                                                filename, |                                                                filename, | ||||||
|   | |||||||
| @@ -34,6 +34,7 @@ from cps.services import gmail | |||||||
| from cps.embed_helper import do_calibre_export | from cps.embed_helper import do_calibre_export | ||||||
| from cps import logger, config | from cps import logger, config | ||||||
| from cps import gdriveutils | from cps import gdriveutils | ||||||
|  | from cps.string_helper import strip_whitespaces | ||||||
| import uuid | import uuid | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
| @@ -127,9 +128,9 @@ class TaskEmail(CalibreTask): | |||||||
|         try: |         try: | ||||||
|             # Parse out the address from the From line, and then the domain from that |             # Parse out the address from the From line, and then the domain from that | ||||||
|             from_email = parseaddr(self.settings["mail_from"])[1] |             from_email = parseaddr(self.settings["mail_from"])[1] | ||||||
|             msgid_domain = from_email.partition('@')[2].strip() |             msgid_domain = strip_whitespaces(from_email.partition('@')[2]) | ||||||
|             # This can sometimes sneak through parseaddr if the input is malformed |             # This can sometimes sneak through parseaddr if the input is malformed | ||||||
|             msgid_domain = msgid_domain.rstrip('>').strip() |             msgid_domain = strip_whitespaces(msgid_domain.rstrip('>')) | ||||||
|         except Exception: |         except Exception: | ||||||
|             msgid_domain = '' |             msgid_domain = '' | ||||||
|         return msgid_domain or 'calibre-web.com' |         return msgid_domain or 'calibre-web.com' | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								cps/ub.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								cps/ub.py
									
									
									
									
									
								
							| @@ -54,7 +54,7 @@ from sqlalchemy.orm import backref, relationship, sessionmaker, Session, scoped_ | |||||||
| from werkzeug.security import generate_password_hash | from werkzeug.security import generate_password_hash | ||||||
|  |  | ||||||
| from . import constants, logger | from . import constants, logger | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
|  |  | ||||||
| @@ -196,19 +196,19 @@ class UserBase: | |||||||
|  |  | ||||||
|     def list_denied_tags(self): |     def list_denied_tags(self): | ||||||
|         mct = self.denied_tags or "" |         mct = self.denied_tags or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def list_allowed_tags(self): |     def list_allowed_tags(self): | ||||||
|         mct = self.allowed_tags or "" |         mct = self.allowed_tags or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def list_denied_column_values(self): |     def list_denied_column_values(self): | ||||||
|         mct = self.denied_column_value or "" |         mct = self.denied_column_value or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def list_allowed_column_values(self): |     def list_allowed_column_values(self): | ||||||
|         mct = self.allowed_column_value or "" |         mct = self.allowed_column_value or "" | ||||||
|         return [t.strip() for t in mct.split(",")] |         return [strip_whitespaces(t) for t in mct.split(",")] | ||||||
|  |  | ||||||
|     def get_view_property(self, page, prop): |     def get_view_property(self, page, prop): | ||||||
|         if not self.view_settings.get(page): |         if not self.view_settings.get(page): | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ from . import logger, comic, isoLanguages | |||||||
| from .constants import BookMeta | from .constants import BookMeta | ||||||
| from .helper import split_authors | from .helper import split_authors | ||||||
| from .file_helper import get_temp_dir | from .file_helper import get_temp_dir | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
| log = logger.create() | log = logger.create() | ||||||
|  |  | ||||||
| @@ -97,9 +98,9 @@ def process(tmp_file_path, original_file_name, original_file_extension, rar_exec | |||||||
|     except Exception as ex: |     except Exception as ex: | ||||||
|         log.warning('cannot parse metadata, using default: %s', ex) |         log.warning('cannot parse metadata, using default: %s', ex) | ||||||
|  |  | ||||||
|     if not meta.title.strip(): |     if not strip_whitespaces(meta.title): | ||||||
|         meta = meta._replace(title=original_file_name) |         meta = meta._replace(title=original_file_name) | ||||||
|     if not meta.author.strip() or meta.author.lower() == 'unknown': |     if not strip_whitespaces(meta.author) or meta.author.lower() == 'unknown': | ||||||
|         meta = meta._replace(author=_('Unknown')) |         meta = meta._replace(author=_('Unknown')) | ||||||
|     return meta |     return meta | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								cps/web.py
									
									
									
									
									
								
							| @@ -60,6 +60,7 @@ from . import limiter | |||||||
| from .services.worker import WorkerThread | from .services.worker import WorkerThread | ||||||
| from .tasks_status import render_task_status | from .tasks_status import render_task_status | ||||||
| from .usermanagement import user_login_required | from .usermanagement import user_login_required | ||||||
|  | from .string_helper import strip_whitespaces | ||||||
|  |  | ||||||
|  |  | ||||||
| feature_support = { | feature_support = { | ||||||
| @@ -1286,7 +1287,7 @@ def register_post(): | |||||||
|     if not config.get_mail_server_configured(): |     if not config.get_mail_server_configured(): | ||||||
|         flash(_("Oops! Email server is not configured, please contact your administrator."), category="error") |         flash(_("Oops! Email server is not configured, please contact your administrator."), category="error") | ||||||
|         return render_title_template('register.html', title=_("Register"), page="register") |         return render_title_template('register.html', title=_("Register"), page="register") | ||||||
|     nickname = to_save.get("email", "").strip() if config.config_register_email else to_save.get('name') |     nickname = strip_whitespaces(to_save.get("email", "")) if config.config_register_email else to_save.get('name') | ||||||
|     if not nickname or not to_save.get("email"): |     if not nickname or not to_save.get("email"): | ||||||
|         flash(_("Oops! Please complete all fields."), category="error") |         flash(_("Oops! Please complete all fields."), category="error") | ||||||
|         return render_title_template('register.html', title=_("Register"), page="register") |         return render_title_template('register.html', title=_("Register"), page="register") | ||||||
| @@ -1311,7 +1312,7 @@ def register_post(): | |||||||
|             ub.session.commit() |             ub.session.commit() | ||||||
|             if feature_support['oauth']: |             if feature_support['oauth']: | ||||||
|                 register_user_with_oauth(content) |                 register_user_with_oauth(content) | ||||||
|             send_registration_mail(to_save.get("email", "").strip(), nickname, password) |             send_registration_mail(strip_whitespaces(to_save.get("email", "")), nickname, password) | ||||||
|         except Exception: |         except Exception: | ||||||
|             ub.session.rollback() |             ub.session.rollback() | ||||||
|             flash(_("Oops! An unknown error occurred. Please try again later."), category="error") |             flash(_("Oops! An unknown error occurred. Please try again later."), category="error") | ||||||
| @@ -1370,11 +1371,11 @@ def login(): | |||||||
|  |  | ||||||
|  |  | ||||||
| @web.route('/login', methods=['POST']) | @web.route('/login', methods=['POST']) | ||||||
| @limiter.limit("40/day", key_func=lambda: request.form.get('username', "").strip().lower()) | @limiter.limit("40/day", key_func=lambda: strip_whitespaces(request.form.get('username', "")).lower()) | ||||||
| @limiter.limit("3/minute", key_func=lambda: request.form.get('username', "").strip().lower()) | @limiter.limit("3/minute", key_func=lambda: strip_whitespaces(request.form.get('username', "")).lower()) | ||||||
| def login_post(): | def login_post(): | ||||||
|     form = request.form.to_dict() |     form = request.form.to_dict() | ||||||
|     username = form.get('username', "").strip().lower().replace("\n","").replace("\r","") |     username = strip_whitespaces(form.get('username', "")).lower().replace("\n","").replace("\r","") | ||||||
|     try: |     try: | ||||||
|         limiter.check() |         limiter.check() | ||||||
|     except RateLimitExceeded: |     except RateLimitExceeded: | ||||||
|   | |||||||
| @@ -37,20 +37,20 @@ | |||||||
|       <div class="row"> |       <div class="row"> | ||||||
|         <div class="col-xs-6 col-md-6 col-sm-offset-3" style="margin-top:50px;"> |         <div class="col-xs-6 col-md-6 col-sm-offset-3" style="margin-top:50px;"> | ||||||
|              |              | ||||||
|             <p class='text-justify attribute'><strong>Start Time: </strong>2024-08-11 19:57:31</p> |             <p class='text-justify attribute'><strong>Start Time: </strong>2024-08-12 18:42:30</p> | ||||||
|              |              | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|         <div class="col-xs-6 col-md-6 col-sm-offset-3"> |         <div class="col-xs-6 col-md-6 col-sm-offset-3"> | ||||||
|              |              | ||||||
|             <p class='text-justify attribute'><strong>Stop Time: </strong>2024-08-12 03:10:54</p> |             <p class='text-justify attribute'><strong>Stop Time: </strong>2024-08-13 01:57:45</p> | ||||||
|              |              | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
|         <div class="col-xs-6 col-md-6 col-sm-offset-3"> |         <div class="col-xs-6 col-md-6 col-sm-offset-3"> | ||||||
|            <p class='text-justify attribute'><strong>Duration: </strong>5h 59 min</p> |            <p class='text-justify attribute'><strong>Duration: </strong>6h 1 min</p> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       </div> |       </div> | ||||||
| @@ -4519,11 +4519,11 @@ ModuleNotFoundError: No module named 'build_release'</pre> | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="failClass"> |     <tr id="su" class="skipClass"> | ||||||
|         <td>TestThumbnails</td> |         <td>TestThumbnails</td> | ||||||
|         <td class="text-center">8</td> |         <td class="text-center">8</td> | ||||||
|         <td class="text-center">6</td> |         <td class="text-center">7</td> | ||||||
|         <td class="text-center">1</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">1</td> |         <td class="text-center">1</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
| @@ -4560,31 +4560,11 @@ ModuleNotFoundError: No module named 'build_release'</pre> | |||||||
|      |      | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id="ft51.4" class="none bg-danger"> |         <tr id='pt51.4' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestThumbnails - test_cover_change_on_upload_new_cover</div> |                 <div class='testcase'>TestThumbnails - test_cover_change_on_upload_new_cover</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6'> |             <td colspan='6' align='center'>PASS</td> | ||||||
|                 <div class="text-center"> |  | ||||||
|                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft51.4')">FAIL</a> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup start--> |  | ||||||
|                 <div id="div_ft51.4" class="popup_window test_output" style="display:block;"> |  | ||||||
|                     <div class='close_button pull-right'> |  | ||||||
|                         <button type="button" class="close" aria-label="Close" onfocus="this.blur();" |  | ||||||
|                                 onclick="document.getElementById('div_ft51.4').style.display='none'"><span |  | ||||||
|                                 aria-hidden="true">×</span></button> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="text-left pull-left"> |  | ||||||
|                         <pre class="text-left">Traceback (most recent call last): |  | ||||||
|   File "/home/ozzie/Development/calibre-web-test/test/test_thumbnails.py", line 140, in test_cover_change_on_upload_new_cover |  | ||||||
|     self.assertGreaterEqual(diff(BytesIO(updated_cover), BytesIO(original_cover), delete_diff_file=True), 0.03) |  | ||||||
| AssertionError: 0.023989181595169266 not greater than or equal to 0.03</pre> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="clearfix"></div> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup end--> |  | ||||||
|             </td> |  | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -4739,11 +4719,11 @@ AssertionError: 0.023989181595169266 not greater than or equal to 0.03</pre> | |||||||
|      |      | ||||||
|  |  | ||||||
|  |  | ||||||
|     <tr id="su" class="failClass"> |     <tr id="su" class="passClass"> | ||||||
|         <td>TestUploadAudio</td> |         <td>TestUploadAudio</td> | ||||||
|         <td class="text-center">12</td> |         <td class="text-center">12</td> | ||||||
|         <td class="text-center">11</td> |         <td class="text-center">12</td> | ||||||
|         <td class="text-center">1</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center">0</td> |         <td class="text-center">0</td> | ||||||
|         <td class="text-center"> |         <td class="text-center"> | ||||||
| @@ -4780,33 +4760,11 @@ AssertionError: 0.023989181595169266 not greater than or equal to 0.03</pre> | |||||||
|      |      | ||||||
|      |      | ||||||
|      |      | ||||||
|         <tr id="ft53.4" class="none bg-danger"> |         <tr id='pt53.4' class='hiddenRow bg-success'> | ||||||
|             <td> |             <td> | ||||||
|                 <div class='testcase'>TestUploadAudio - test_upload_flac</div> |                 <div class='testcase'>TestUploadAudio - test_upload_flac</div> | ||||||
|             </td> |             </td> | ||||||
|             <td colspan='6'> |             <td colspan='6' align='center'>PASS</td> | ||||||
|                 <div class="text-center"> |  | ||||||
|                     <a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft53.4')">FAIL</a> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup start--> |  | ||||||
|                 <div id="div_ft53.4" class="popup_window test_output" style="display:block;"> |  | ||||||
|                     <div class='close_button pull-right'> |  | ||||||
|                         <button type="button" class="close" aria-label="Close" onfocus="this.blur();" |  | ||||||
|                                 onclick="document.getElementById('div_ft53.4').style.display='none'"><span |  | ||||||
|                                 aria-hidden="true">×</span></button> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="text-left pull-left"> |  | ||||||
|                         <pre class="text-left">Traceback (most recent call last): |  | ||||||
|   File "/home/ozzie/Development/calibre-web-test/test/test_upload_audio.py", line 367, in test_upload_flac |  | ||||||
|     self.assertEqual('Album', details['series']) |  | ||||||
| AssertionError: 'Album' != 'Flac Album' |  | ||||||
| - Album |  | ||||||
| + Flac Album</pre> |  | ||||||
|                     </div> |  | ||||||
|                     <div class="clearfix"></div> |  | ||||||
|                 </div> |  | ||||||
|                 <!--css div popup end--> |  | ||||||
|             </td> |  | ||||||
|         </tr> |         </tr> | ||||||
|      |      | ||||||
|      |      | ||||||
| @@ -5849,8 +5807,8 @@ AssertionError: 'Album' != 'Flac Album' | |||||||
|     <tr id='total_row' class="text-center bg-grey"> |     <tr id='total_row' class="text-center bg-grey"> | ||||||
|         <td>Total</td> |         <td>Total</td> | ||||||
|         <td>519</td> |         <td>519</td> | ||||||
|         <td>506</td> |         <td>508</td> | ||||||
|         <td>2</td> |         <td>0</td> | ||||||
|         <td>2</td> |         <td>2</td> | ||||||
|         <td>9</td> |         <td>9</td> | ||||||
|         <td> </td> |         <td> </td> | ||||||
| @@ -6390,7 +6348,7 @@ AssertionError: 'Album' != 'Flac Album' | |||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
|     drawCircle(506, 2, 2, 9); |     drawCircle(508, 0, 2, 9); | ||||||
|     showCase(5); |     showCase(5); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ozzie Isaacs
					Ozzie Isaacs