diff --git a/cps/gdriveutils.py b/cps/gdriveutils.py index c765b9ab..49ab5882 100644 --- a/cps/gdriveutils.py +++ b/cps/gdriveutils.py @@ -21,6 +21,7 @@ import json import shutil import chardet import ssl +import sqlite3 from flask import Response, stream_with_context from sqlalchemy import create_engine @@ -258,13 +259,17 @@ def getEbooksFolderId(drive=None): return gDriveId.gdrive_id -def getFile(pathId, fileName, drive): - metaDataFile = "'%s' in parents and trashed = false and title = '%s'" % (pathId, fileName.replace("'", r"\'")) +def getFile(pathId, fileName, drive, nocase): + metaDataFile = "'%s' in parents and trashed = false and title contains '%s'" % (pathId, fileName.replace("'", r"\'")) fileList = drive.ListFile({'q': metaDataFile}).GetList() if fileList.__len__() == 0: return None - else: + if nocase: return fileList[0] + for f in fileList: + if f['title'] == fileName: + return f + return None def getFolderId(path, drive): @@ -303,7 +308,7 @@ def getFolderId(path, drive): session.commit() else: currentFolderId = storedPathName.gdrive_id - except (OperationalError, IntegrityError, StaleDataError) as ex: + except (OperationalError, IntegrityError, StaleDataError, sqlite3.IntegrityError) as ex: log.error_or_exception('Database error: {}'.format(ex)) session.rollback() except ApiRequestError as ex: @@ -314,7 +319,7 @@ def getFolderId(path, drive): return currentFolderId -def getFileFromEbooksFolder(path, fileName): +def getFileFromEbooksFolder(path, fileName, nocase=False): drive = getDrive(Gdrive.Instance().drive) if path: # sqlCheckPath=path if path[-1] =='/' else path + '/' @@ -322,7 +327,7 @@ def getFileFromEbooksFolder(path, fileName): else: folderId = getEbooksFolderId(drive) if folderId: - return getFile(folderId, fileName, drive) + return getFile(folderId, fileName, drive, nocase) else: return None @@ -338,12 +343,12 @@ def downloadFile(path, filename, output): f.GetContentFile(output) -def moveGdriveFolderRemote(origin_file, target_folder): +def moveGdriveFolderRemote(origin_file, target_folder, single_book=False): drive = getDrive(Gdrive.Instance().drive) previous_parents = ",".join([parent["id"] for parent in origin_file.get('parents')]) children = drive.auth.service.children().list(folderId=previous_parents).execute() - gFileTargetDir = getFileFromEbooksFolder(None, target_folder) - if not gFileTargetDir: + if single_book: + # gFileTargetDir = getFileFromEbooksFolder(None, target_folder, nocase=True) gFileTargetDir = drive.CreateFile( {'title': target_folder, 'parents': [{"kind": "drive#fileLink", 'id': getEbooksFolderId()}], "mimeType": "application/vnd.google-apps.folder"}) @@ -353,19 +358,20 @@ def moveGdriveFolderRemote(origin_file, target_folder): addParents=gFileTargetDir['id'], removeParents=previous_parents, fields='id, parents').execute() - - elif gFileTargetDir['title'] != target_folder: - deleteDatabasePath(gFileTargetDir['title']) + elif origin_file['title'] != target_folder: + #gFileTargetDir = getFileFromEbooksFolder(None, target_folder, nocase=True) + #if gFileTargetDir: + deleteDatabasePath(origin_file['title']) # Folder is not existing, create, and move folder drive.auth.service.files().patch(fileId=origin_file['id'], body={'title': target_folder}, fields='title').execute() - else: + '''else: # Move the file to the new folder drive.auth.service.files().update(fileId=origin_file['id'], addParents=gFileTargetDir['id'], removeParents=previous_parents, - fields='id, parents').execute() + fields='id, parents').execute()''' # if previous_parents has no children anymore, delete original fileparent if len(children['items']) == 1: deleteDatabaseEntry(previous_parents) diff --git a/cps/helper.py b/cps/helper.py index b70cbbe0..85f1689b 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -479,7 +479,10 @@ def update_dir_structure_file(book_id, calibre_path, original_filepath, new_auth title_dir = local_book.path.split('/')[1] new_title_dir = get_valid_filename(local_book.title, chars=96) + " (" + str(book_id) + ")" - new_author_dir = get_valid_filename(new_author, chars=96) + if new_author: + new_author_dir = get_valid_filename(new_author, chars=96) + else: + new_author = new_author_dir = author_dir if title_dir != new_title_dir or author_dir != new_author_dir or original_filepath: error = move_files_on_change(calibre_path, @@ -533,9 +536,9 @@ def update_dir_structure_gdrive(book_id, first_author): return _('File %(file)s not found on Google Drive', file=book.path) # file not found if authordir != new_authordir: - g_file = gd.getFileFromEbooksFolder(os.path.dirname(book.path), new_titledir) + g_file = gd.getFileFromEbooksFolder(authordir, new_titledir) if g_file: - gd.moveGdriveFolderRemote(g_file, new_authordir) + gd.moveGdriveFolderRemote(g_file, new_authordir, single_book=True) book.path = new_authordir + '/' + book.path.split('/')[1] gd.updateDatabaseOnEdit(g_file['id'], book.path) else: diff --git a/cps/web.py b/cps/web.py index abe62c96..3e0fce9a 100644 --- a/cps/web.py +++ b/cps/web.py @@ -107,7 +107,7 @@ def add_security_headers(resp): resp.headers['X-Content-Type-Options'] = 'nosniff' resp.headers['X-Frame-Options'] = 'SAMEORIGIN' resp.headers['X-XSS-Protection'] = '1; mode=block' - resp.headers['Strict-Transport-Security'] = 'max-age=31536000;' + resp.headers['Strict-Transport-Security'] = 'max-age=31536000'; return resp diff --git a/test/Calibre-Web TestSummary_Linux.html b/test/Calibre-Web TestSummary_Linux.html index bb9f8214..b799e9aa 100644 --- a/test/Calibre-Web TestSummary_Linux.html +++ b/test/Calibre-Web TestSummary_Linux.html @@ -37,20 +37,20 @@
-

Start Time: 2024-06-28 20:08:21

+

Start Time: 2024-06-29 20:48:57

-

Stop Time: 2024-06-29 02:31:07

+

Stop Time: 2024-06-30 03:48:15

-

Duration: 5h 10 min

+

Duration: 5h 44 min

@@ -234,11 +234,11 @@ - + TestBackupMetadata 21 - 19 - 2 + 21 + 0 0 0 @@ -257,38 +257,11 @@ - +
TestBackupMetadata - test_backup_change_book_author
- -
- FAIL -
- - - - + PASS @@ -365,32 +338,11 @@ First extra element 0: - +
TestBackupMetadata - test_backup_change_book_title
- -
- FAIL -
- - - - + PASS @@ -510,59 +462,145 @@ AssertionError: '' != 'The bok Lo,执|1u' - - _ErrorHolder - 1 + + TestCli + 13 + 13 0 0 - 1 0 - Detail + Detail - + -
setUpClass (test_cli)
+
TestCli - test_already_started
- -
- ERROR -
- - - + PASS + + + + + + +
TestCli - test_bind_to_single_interface
+ PASS + + + + + + +
TestCli - test_change_password
+ + PASS + + + + + + +
TestCli - test_cli_SSL_files
+ + PASS + + + + + + +
TestCli - test_cli_different_folder
+ + PASS + + + + + + +
TestCli - test_cli_different_settings_database
+ + PASS + + + + + + +
TestCli - test_dryrun_update
+ + PASS + + + + + + +
TestCli - test_enable_reconnect
+ + PASS + + + + + + +
TestCli - test_environ_port_setting
+ + PASS + + + + + + +
TestCli - test_logfile
+ + PASS + + + + + + +
TestCli - test_no_database
+ + PASS + + + + + + +
TestCli - test_settingsdb_not_writeable
+ + PASS + + + + + + +
TestCli - test_writeonly_static_files
+ + PASS - + TestCliGdrivedb 4 - 0 4 0 0 + 0 Detail @@ -570,131 +608,38 @@ FileNotFoundError: [Errno 2] No such file or directory: './Calibre_db' +
TestCliGdrivedb - test_cli_gdrive_folder
- -
- FAIL -
- - - - + PASS - +
TestCliGdrivedb - test_cli_gdrive_location
- -
- FAIL -
- - - - + PASS - +
TestCliGdrivedb - test_gdrive_db_nonwrite
- -
- FAIL -
- - - - + PASS - +
TestCliGdrivedb - test_no_database
- -
- FAIL -
- - - - + PASS @@ -1060,11 +1005,11 @@ AssertionError: True is not false : Inital config failed with normal database

+ TestEditAdditionalBooks 20 - 17 - 1 + 18 + 0 0 2 @@ -1235,31 +1180,11 @@ AssertionError: True is not false : Inital config failed with normal database

+
TestEditAdditionalBooks - test_writeonly_path
- -
- FAIL -
- - - - + PASS @@ -1292,11 +1217,11 @@ AssertionError: False is not true - + TestEditBooks 38 - 35 - 1 + 36 + 0 0 2 @@ -1315,31 +1240,11 @@ AssertionError: False is not true - +
TestEditBooks - test_edit_author
- -
- FAIL -
- - - - + PASS @@ -1705,13 +1610,13 @@ AssertionError: False is not true TestEditAuthors - 7 - 7 + 8 + 8 0 0 0 - Detail + Detail @@ -1746,7 +1651,7 @@ AssertionError: False is not true -
TestEditAuthors - test_change_capital_rename_co_author
+
TestEditAuthors - test_change_capital_one_author_two_books_coauthor
PASS @@ -1755,7 +1660,7 @@ AssertionError: False is not true -
TestEditAuthors - test_change_capital_rename_two_co_authors
+
TestEditAuthors - test_change_capital_rename_co_author
PASS @@ -1764,7 +1669,7 @@ AssertionError: False is not true -
TestEditAuthors - test_rename_author_accent_onupload
+
TestEditAuthors - test_change_capital_rename_two_co_authors
PASS @@ -1772,6 +1677,15 @@ AssertionError: False is not true + +
TestEditAuthors - test_rename_author_accent_onupload
+ + PASS + + + + +
TestEditAuthors - test_rename_capital_on_upload
@@ -1783,72 +1697,32 @@ AssertionError: False is not true TestEditAuthorsGdrive - 6 - 0 - 6 + 7 + 5 + 2 0 0 - Detail + Detail - +
TestEditAuthorsGdrive - test_change_capital_co_author
- -
- FAIL -
- - - - + PASS - +
TestEditAuthorsGdrive - test_change_capital_one_author_one_book
- -
- FAIL -
- - - - + PASS @@ -1870,11 +1744,9 @@ AssertionError: <selenium.webdriver.remote.webelement.WebElement (session=
Traceback (most recent call last):
-  File "/home/ozzie/Development/calibre-web-test/test/test_edit_books_author_gdrive.py", line 253, in test_change_capital_one_author_two_books
-    self.assertCountEqual(['Frodo Beutlin', 'Norbert halagal', 'Liu Yang', 'Hector Gonçalves'], details['author'])
-AssertionError: Element counts were not equal:
-First has 1, Second has 0:  'Liu Yang'
-First has 0, Second has 1:  'Liu yang'
+ File "/home/ozzie/Development/calibre-web-test/test/test_edit_books_author_gdrive.py", line 174, in test_change_capital_one_author_two_books + self.assertFalse(self.check_element_on_page((By.ID, "flash_danger"))) +AssertionError: <selenium.webdriver.remote.webelement.WebElement (session="75cab94e-bc8d-4b29-b4fa-bcb013c9fe05", element="4bd75a44-1bfc-4cf4-a39d-36e9675ec783")> is not false
@@ -1884,38 +1756,18 @@ First has 0, Second has 1: 'Liu yang' - + -
TestEditAuthorsGdrive - test_change_capital_rename_co_author
- - -
- FAIL -
- - - +
TestEditAuthorsGdrive - test_change_capital_one_author_two_books_coauthor
+ PASS -
TestEditAuthorsGdrive - test_change_capital_rename_two_co_authors
+
TestEditAuthorsGdrive - test_change_capital_rename_co_author
@@ -1930,9 +1782,9 @@ AssertionError: False is not true
Traceback (most recent call last):
-  File "/home/ozzie/Development/calibre-web-test/test/test_edit_books_author_gdrive.py", line 463, in test_change_capital_rename_two_co_authors
-    self.assertFalse(self.check_element_on_page((By.ID, "flash_danger")))
-AssertionError: <selenium.webdriver.remote.webelement.WebElement (session="2035360a-7d0e-4230-ba6e-0809c52d1958", element="a04a321a-7396-4621-84a6-a40ec9d11340")> is not false
+ File "/home/ozzie/Development/calibre-web-test/test/test_edit_books_author_gdrive.py", line 370, in test_change_capital_rename_co_author + self.assertTrue(fs.isfile(os.path.join('test', 'hector Gonçalves/book9 (11)', +AssertionError: False is not true
@@ -1942,26 +1794,411 @@ AssertionError: <selenium.webdriver.remote.webelement.WebElement (session= - + + +
TestEditAuthorsGdrive - test_change_capital_rename_two_co_authors
+ + PASS + + + + +
TestEditAuthorsGdrive - test_rename_capital_on_upload
+ PASS + + + + + + + TestEditBooksList + 19 + 15 + 3 + 1 + 0 + + Detail + + + + + + + +
TestEditBooksList - test_booklist_xss: r = requests.session()
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_author
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_categories
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_comment
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_category
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_comment
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_enum
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_float
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_int
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_ratings
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_cust_text
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_languages
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_publisher
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_series
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_seriesindex
+ + PASS + + + + + + +
TestEditBooksList - test_bookslist_edit_title
+
- FAIL + ERROR
-