Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian....@packages.debian.org
Usertags: pu
X-Debbugs-Cc: tbs...@packages.debian.org, mechti...@debian.org
Control: affects -1 + src:tbsync

[ Reason ]

This package is an extension to thunderbird. After thunderbird is updated to version 115.* in bookwork it is necessary to update this extension too.

[ Impact ]

Otherwise this extension doesn't work anymore

[ Risks ]

Only dav4tbsync and eas4tbsync are affected and will be updated too

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]

There is a new version of tbsync to work with thunderbird 115.x

[ Other info ]

The output von debdiff (stable vs stable-pu is attached)

dav4tbsync and eas4tbsync will follow

Kind regards to the release team

Mechtilde


--
Mechtilde Stehmann
## Debian Developer
## PGP encryption welcome
## F0E3 7F3D C87A 4998 2899  39E7 F287 7BBA 141A AD7F
diffstat for tbsync-4.3 tbsync-4.7

 _locales/bg/messages.json                     |    7 
 _locales/cs/messages.json                     |    7 
 _locales/de/messages.json                     |   91 +--
 _locales/en-US/messages.json                  |    7 
 _locales/es/messages.json                     |    7 
 _locales/et/messages.json                     |    7 
 _locales/fr/messages.json                     |    7 
 _locales/gl/messages.json                     |    9 
 _locales/hu/messages.json                     |    7 
 _locales/it/messages.json                     |    7 
 _locales/ja/messages.json                     |    7 
 _locales/ko/messages.json                     |    7 
 _locales/pl/messages.json                     |    7 
 _locales/pt_BR/messages.json                  |    7 
 _locales/ro/messages.json                     |    7 
 _locales/ru/messages.json                     |    7 
 _locales/sv/messages.json                     |    7 
 content/api/BootstrapLoader/CHANGELOG.md      |   15 
 content/api/BootstrapLoader/implementation.js |  676 ++++++++++++++++++++------
 content/api/BootstrapLoader/schema.json       |    4 
 content/manager/accounts.js                   |   12 
 content/manager/accounts.xhtml                |    4 
 content/manager/editAccount.js                |    3 
 content/manager/editAccount.xhtml             |    7 
 content/manager/eventlog/eventlog.js          |    9 
 content/manager/eventlog/eventlog.xhtml       |   14 
 content/modules/db.js                         |   13 
 content/modules/io.js                         |    4 
 content/modules/lightning.js                  |    2 
 content/modules/manager.js                    |   11 
 content/passwordPrompt/passwordPrompt.css     |   13 
 content/passwordPrompt/passwordPrompt.js      |    8 
 content/passwordPrompt/passwordPrompt.xhtml   |   44 -
 content/tbsync.jsm                            |    3 
 debian/changelog                              |   26 +
 debian/control                                |    6 
 debian/gbp.conf                               |    2 
 manifest.json                                 |    4 
 38 files changed, 800 insertions(+), 285 deletions(-)

diff -Nru tbsync-4.3/content/api/BootstrapLoader/CHANGELOG.md tbsync-4.7/content/api/BootstrapLoader/CHANGELOG.md
--- tbsync-4.3/content/api/BootstrapLoader/CHANGELOG.md	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/api/BootstrapLoader/CHANGELOG.md	2023-08-29 22:22:49.000000000 +0200
@@ -1,3 +1,18 @@
+Version: 1.21
+-------------
+- Explicitly set hasAddonManagerEventListeners flag to false on uninstall
+
+Version: 1.20
+-------------
+- hard fork BootstrapLoader v1.19 implementation and continue to serve it for
+  Thunderbird 111 and older
+- BootstrapLoader v1.20 has removed a lot of unnecessary code used for backward
+  compatibility
+
+Version: 1.19
+-------------
+- fix race condition which could prevent the AOM tab to be monkey patched correctly
+
 Version: 1.18
 -------------
 - be precise on which revision the wrench symbol should be displayed, instead of
diff -Nru tbsync-4.3/content/api/BootstrapLoader/implementation.js tbsync-4.7/content/api/BootstrapLoader/implementation.js
--- tbsync-4.3/content/api/BootstrapLoader/implementation.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/api/BootstrapLoader/implementation.js	2023-08-29 22:22:49.000000000 +0200
@@ -2,7 +2,7 @@
  * This file is provided by the addon-developer-support repository at
  * https://github.com/thundernest/addon-developer-support
  *
- * Version: 1.18
+ * Version: 1.21
  *
  * Author: John Bieling (j...@thunderbird.net)
  *
@@ -17,70 +17,65 @@
 var { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-var BootstrapLoader = class extends ExtensionCommon.ExtensionAPI {
-  getMessenger(context) {   
-    let apis = [
-      "storage",
-      "runtime",
-      "extension",
-      "i18n",
-    ];
-
-    function getStorage() {
-      let localstorage = null;
-      try {
-        localstorage = context.apiCan.findAPIPath("storage");
-        localstorage.local.get = (...args) =>
-          localstorage.local.callMethodInParentProcess("get", args);
-        localstorage.local.set = (...args) =>
-          localstorage.local.callMethodInParentProcess("set", args);
-        localstorage.local.remove = (...args) =>
-          localstorage.local.callMethodInParentProcess("remove", args);
-        localstorage.local.clear = (...args) =>
-          localstorage.local.callMethodInParentProcess("clear", args);
-      } catch (e) {
-        console.info("Storage permission is missing");
-      }
-      return localstorage;
-    }
-    
-    let messenger = {};    
-    for (let api of apis) {
-      switch (api) {
-        case "storage":
-          XPCOMUtils.defineLazyGetter(messenger, "storage", () =>
-            getStorage()
-          );
-        break;
+function getThunderbirdVersion() {
+  let parts = Services.appinfo.version.split(".");
+  return {
+    major: parseInt(parts[0]),
+    minor: parseInt(parts[1]),
+    revision: parts.length > 2 ? parseInt(parts[2]) : 0,
+  }
+}
 
-        default:
-          XPCOMUtils.defineLazyGetter(messenger, api, () =>
-            context.apiCan.findAPIPath(api)
-          );
-      }
+function getMessenger(context) {
+  let apis = ["storage", "runtime", "extension", "i18n"];
+
+  function getStorage() {
+    let localstorage = null;
+    try {
+      localstorage = context.apiCan.findAPIPath("storage");
+      localstorage.local.get = (...args) =>
+        localstorage.local.callMethodInParentProcess("get", args);
+      localstorage.local.set = (...args) =>
+        localstorage.local.callMethodInParentProcess("set", args);
+      localstorage.local.remove = (...args) =>
+        localstorage.local.callMethodInParentProcess("remove", args);
+      localstorage.local.clear = (...args) =>
+        localstorage.local.callMethodInParentProcess("clear", args);
+    } catch (e) {
+      console.info("Storage permission is missing");
     }
-    return messenger;
+    return localstorage;
   }
 
-  getThunderbirdVersion() {
-    let parts = Services.appinfo.version.split(".");
-    return {
-      major: parseInt(parts[0]),
-      minor: parseInt(parts[1]),
-      revision: parts.length > 2 ? parseInt(parts[2]) : 0,
+  let messenger = {};
+  for (let api of apis) {
+    switch (api) {
+      case "storage":
+        XPCOMUtils.defineLazyGetter(messenger, "storage", () =>
+          getStorage()
+        );
+        break;
+
+      default:
+        XPCOMUtils.defineLazyGetter(messenger, api, () =>
+          context.apiCan.findAPIPath(api)
+        );
     }
   }
-  
+  return messenger;
+}
+
+var BootstrapLoader_102 = class extends ExtensionCommon.ExtensionAPI {
   getCards(e) {
     // This gets triggered by real events but also manually by providing the outer window.
     // The event is attached to the outer browser, get the inner one.
     let doc;
-    
+
     // 78,86, and 87+ need special handholding. *Yeah*.
-    if (this.getThunderbirdVersion().major < 86) {
+    if (getThunderbirdVersion().major < 86) {
       let ownerDoc = e.document || e.target.ownerDocument;
       doc = ownerDoc.getElementById("html-view-browser").contentDocument;
-    } else if (this.getThunderbirdVersion().major < 87) {
+    } else if (getThunderbirdVersion().major < 87) {
       let ownerDoc = e.document || e.target;
       doc = ownerDoc.getElementById("html-view-browser").contentDocument;
     } else {
@@ -88,42 +83,42 @@
     }
     return doc.querySelectorAll("addon-card");
   }
-  
+
   // Add pref entry to 68
   add68PrefsEntry(event) {
     let id = this.menu_addonPrefs_id + "_" + this.uniqueRandomID;
 
     // Get the best size of the icon (16px or bigger)
-    let iconSizes = this.extension.manifest.icons 
+    let iconSizes = this.extension.manifest.icons
       ? Object.keys(this.extension.manifest.icons)
       : [];
-    iconSizes.sort((a,b)=>a-b);
+    iconSizes.sort((a, b) => a - b);
     let bestSize = iconSizes.filter(e => parseInt(e) >= 16).shift();
     let icon = bestSize ? this.extension.manifest.icons[bestSize] : "";
 
     let name = this.extension.manifest.name;
     let entry = icon
       ? event.target.ownerGlobal.MozXULElement.parseXULToFragment(
-          `<menuitem class="menuitem-iconic" id="${id}" image="${icon}" label="${name}" />`)
-      :  event.target.ownerGlobal.MozXULElement.parseXULToFragment(
-          `<menuitem id="${id}" label="${name}" />`);
-    
+        `<menuitem class="menuitem-iconic" id="${id}" image="${icon}" label="${name}" />`)
+      : event.target.ownerGlobal.MozXULElement.parseXULToFragment(
+        `<menuitem id="${id}" label="${name}" />`);
+
     event.target.appendChild(entry);
     let noPrefsElem = event.target.querySelector('[disabled="true"]');
     // using collapse could be undone by core, so we use display none
     // noPrefsElem.setAttribute("collapsed", "true");
     noPrefsElem.style.display = "none";
     event.target.ownerGlobal.document.getElementById(id).addEventListener("command", this);
-  }   
+  }
 
   // Event handler for the addon manager, to update the state of the options button.
-  handleEvent(e) {   
+  handleEvent(e) {
     switch (e.type) {
       // 68 add-on options menu showing
       case "popupshowing": {
         this.add68PrefsEntry(e);
       }
-      break;
+        break;
 
       // 78/88 add-on options menu/button click
       case "click": {
@@ -131,31 +126,31 @@
         e.stopPropagation();
         let BL = {}
         BL.extension = this.extension;
-        BL.messenger = this.getMessenger(this.context);
+        BL.messenger = getMessenger(this.context);
         let w = Services.wm.getMostRecentWindow("mail:3pane");
-        w.openDialog(this.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL);        
+        w.openDialog(this.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL);
       }
-      break;
-      
+        break;
+
       // 68 add-on options menu command
       case "command": {
         let BL = {}
         BL.extension = this.extension;
-        BL.messenger = this.getMessenger(this.context);
+        BL.messenger = getMessenger(this.context);
         e.target.ownerGlobal.openDialog(this.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL);
       }
-      break;
-      
+        break;
+
       // update, ViewChanged and manual call for add-on manager options overlay
       default: {
         let cards = this.getCards(e);
         for (let card of cards) {
           // Setup either the options entry in the menu or the button
           if (card.addon.id == this.extension.id) {
-            let optionsMenu = 
-              (this.getThunderbirdVersion().major > 78 && this.getThunderbirdVersion().major < 88) ||
-              (this.getThunderbirdVersion().major == 78 && this.getThunderbirdVersion().minor < 10) ||
-              (this.getThunderbirdVersion().major == 78 && this.getThunderbirdVersion().minor == 10 && this.getThunderbirdVersion().revision < 2);
+            let optionsMenu =
+              (getThunderbirdVersion().major > 78 && getThunderbirdVersion().major < 88) ||
+              (getThunderbirdVersion().major == 78 && getThunderbirdVersion().minor < 10) ||
+              (getThunderbirdVersion().major == 78 && getThunderbirdVersion().minor == 10 && getThunderbirdVersion().revision < 2);
             if (optionsMenu) {
               // Options menu in 78.0-78.10 and 79-87
               let addonOptionsLegacyEntry = card.querySelector(".extension-options-legacy");
@@ -204,10 +199,10 @@
           }
         }
       }
-    }      
-  }  
-  
-// Some tab/add-on-manager related functions
+    }
+  }
+
+  // Some tab/add-on-manager related functions
   getTabMail(window) {
     return window.document.getElementById("tabmail");
   }
@@ -215,7 +210,7 @@
   // returns the outer browser, not the nested browser of the add-on manager
   // events must be attached to the outer browser
   getAddonManagerFromTab(tab) {
-    if (tab.browser) {
+    if (tab.browser && tab.mode.name == "contentTab") {
       let win = tab.browser.contentWindow;
       if (win && win.location.href == "about:addons") {
         return win;
@@ -226,9 +221,28 @@
   getAddonManagerFromWindow(window) {
     let tabMail = this.getTabMail(window);
     for (let tab of tabMail.tabInfo) {
-      let win = this.getAddonManagerFromTab(tab)
-      if (win) {
-        return win;
+      let managerWindow = this.getAddonManagerFromTab(tab);
+      if (managerWindow) {
+        return managerWindow;
+      }
+    }
+  }
+
+  async getAddonManagerFromWindowWaitForLoad(window) {
+    let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane");
+
+    let tabMail = this.getTabMail(window);
+    for (let tab of tabMail.tabInfo) {
+      if (tab.browser && tab.mode.name == "contentTab") {
+        // Instead of registering a load observer, wait until its loaded. Not nice,
+        // but gets aroud a lot of edge cases.
+        while (!tab.pageLoaded) {
+          await new Promise(r => setTimeout(r, 150));
+        }
+        let managerWindow = this.getAddonManagerFromTab(tab);
+        if (managerWindow) {
+          return managerWindow;
+        }
       }
     }
   }
@@ -237,15 +251,16 @@
     if (!managerWindow) {
       return;
     }
-    if (managerWindow 
-          && managerWindow[this.uniqueRandomID]
-          && managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners
+    if (
+      managerWindow &&
+      managerWindow[this.uniqueRandomID] &&
+      managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners
     ) {
       return;
     }
     managerWindow.document.addEventListener("ViewChanged", this);
     managerWindow.document.addEventListener("update", this);
-    managerWindow.document.addEventListener("view-loaded", this);    
+    managerWindow.document.addEventListener("view-loaded", this);
     managerWindow[this.uniqueRandomID] = {};
     managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = true;
     if (forceLoad) {
@@ -262,13 +277,13 @@
     this.pathToOptionsPage = null;
     this.chromeHandle = null;
     this.chromeData = null;
-    this.resourceData = null;    
+    this.resourceData = null;
     this.bootstrappedObj = {};
 
     // make the extension object and the messenger object available inside
     // the bootstrapped scope
     this.bootstrappedObj.extension = context.extension;
-    this.bootstrappedObj.messenger = this.getMessenger(this.context);
+    this.bootstrappedObj.messenger = getMessenger(this.context);
 
     this.BOOTSTRAP_REASONS = {
       APP_STARTUP: 1,
@@ -283,49 +298,413 @@
 
     const aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup);
     const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler);
-    
+
     let self = this;
 
     // TabMonitor to detect opening of tabs, to setup the options button in the add-on manager.
     this.tabMonitor = {
-      onTabTitleChanged(aTab) {},
-      onTabClosing(aTab) {},
-      onTabPersist(aTab) {},
-      onTabRestored(aTab) {},
-      onTabSwitched(aNewTab, aOldTab) {
-        //self.setupAddonManager(self.getAddonManagerFromTab(aNewTab));
+      onTabTitleChanged(tab) { },
+      onTabClosing(tab) { },
+      onTabPersist(tab) { },
+      onTabRestored(tab) { },
+      onTabSwitched(aNewTab, aOldTab) { },
+      async onTabOpened(tab) {
+        if (tab.browser && tab.mode.name == "contentTab") {
+          let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane");
+          // Instead of registering a load observer, wait until its loaded. Not nice,
+          // but gets aroud a lot of edge cases.
+          while (!tab.pageLoaded) {
+            await new Promise(r => setTimeout(r, 150));
+          }
+          self.setupAddonManager(self.getAddonManagerFromTab(tab));
+        }
       },
-      async onTabOpened(aTab) {
-        if (aTab.browser) {
-          if (!aTab.pageLoaded) {
-            // await a location change if browser is not loaded yet
-            await new Promise(resolve => {
-              let reporterListener = {
-                QueryInterface: ChromeUtils.generateQI([
-                  "nsIWebProgressListener",
-                  "nsISupportsWeakReference",
-                ]),
-                onStateChange() {},
-                onProgressChange() {},
-                onLocationChange(
-                    /* in nsIWebProgress*/ aWebProgress,
-                    /* in nsIRequest*/ aRequest,
-                    /* in nsIURI*/ aLocation
-                ) {
-                  aTab.browser.removeProgressListener(reporterListener);  
-                  resolve();
-                },
-                onStatusChange() {},
-                onSecurityChange() {},
-                onContentBlockingEvent() {}
-              }          
-              aTab.browser.addProgressListener(reporterListener);  
+    };
+
+    return {
+      BootstrapLoader: {
+
+        registerOptionsPage(optionsUrl) {
+          self.pathToOptionsPage = optionsUrl.startsWith("chrome://")
+            ? optionsUrl
+            : context.extension.rootURI.resolve(optionsUrl);
+        },
+
+        openOptionsDialog(windowId) {
+          let window = context.extension.windowManager.get(windowId, context).window
+          let BL = {}
+          BL.extension = self.extension;
+          BL.messenger = getMessenger(self.context);
+          window.openDialog(self.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL);
+        },
+
+        registerChromeUrl(data) {
+          let chromeData = [];
+          let resourceData = [];
+          for (let entry of data) {
+            if (entry[0] == "resource") resourceData.push(entry);
+            else chromeData.push(entry)
+          }
+
+          if (chromeData.length > 0) {
+            const manifestURI = Services.io.newURI(
+              "manifest.json",
+              null,
+              context.extension.rootURI
+            );
+            self.chromeHandle = aomStartup.registerChrome(manifestURI, chromeData);
+          }
+
+          for (let res of resourceData) {
+            // [ "resource", "shortname" , "path" ]
+            let uri = Services.io.newURI(
+              res[2],
+              null,
+              context.extension.rootURI
+            );
+            resProto.setSubstitutionWithFlags(
+              res[1],
+              uri,
+              resProto.ALLOW_CONTENT_ACCESS
+            );
+          }
+
+          self.chromeData = chromeData;
+          self.resourceData = resourceData;
+        },
+
+        registerBootstrapScript: async function (aPath) {
+          self.pathToBootstrapScript = aPath.startsWith("chrome://")
+            ? aPath
+            : context.extension.rootURI.resolve(aPath);
+
+          // Get the addon object belonging to this extension.
+          let addon = await AddonManager.getAddonByID(context.extension.id);
+          //make the addon globally available in the bootstrapped scope
+          self.bootstrappedObj.addon = addon;
+
+          // add BOOTSTRAP_REASONS to scope
+          for (let reason of Object.keys(self.BOOTSTRAP_REASONS)) {
+            self.bootstrappedObj[reason] = self.BOOTSTRAP_REASONS[reason];
+          }
+
+          // Load registered bootstrap scripts and execute its startup() function.
+          try {
+            if (self.pathToBootstrapScript) Services.scriptloader.loadSubScript(self.pathToBootstrapScript, self.bootstrappedObj, "UTF-8");
+            if (self.bootstrappedObj.startup) self.bootstrappedObj.startup.call(self.bootstrappedObj, self.extension.addonData, self.BOOTSTRAP_REASONS[self.extension.startupReason]);
+          } catch (e) {
+            Components.utils.reportError(e)
+          }
+
+          // Register window listener for main TB window
+          if (self.pathToOptionsPage) {
+            ExtensionSupport.registerWindowListener("injectListener_" + self.uniqueRandomID, {
+              chromeURLs: [
+                "chrome://messenger/content/messenger.xul",
+                "chrome://messenger/content/messenger.xhtml",
+              ],
+              async onLoadWindow(window) {
+                if (getThunderbirdVersion().major < 78) {
+                  let element_addonPrefs = window.document.getElementById(self.menu_addonPrefs_id);
+                  element_addonPrefs.addEventListener("popupshowing", self);
+                } else {
+                  // Add a tabmonitor, to be able to setup the options button/menu in the add-on manager.
+                  self.getTabMail(window).registerTabMonitor(self.tabMonitor);
+                  window[self.uniqueRandomID] = {};
+                  window[self.uniqueRandomID].hasTabMonitor = true;
+                  // Setup the options button/menu in the add-on manager, if it is already open.
+                  let managerWindow = await self.getAddonManagerFromWindowWaitForLoad(window);
+                  self.setupAddonManager(managerWindow, true);
+                }
+              },
+
+              onUnloadWindow(window) {
+              }
             });
           }
-          // Setup the ViewChange event listener in the outer browser of the add-on,
-          // but do not actually add the button/menu, as the inner browser is not yet ready,
-          // let the ViewChange event do it
-          self.setupAddonManager(self.getAddonManagerFromTab(aTab));
+        }
+      }
+    };
+  }
+
+  onShutdown(isAppShutdown) {
+    if (isAppShutdown) {
+      return; // the application gets unloaded anyway
+    }
+
+    //remove our entry in the add-on options menu
+    if (this.pathToOptionsPage) {
+      for (let window of Services.wm.getEnumerator("mail:3pane")) {
+        if (getThunderbirdVersion().major < 78) {
+          let element_addonPrefs = window.document.getElementById(this.menu_addonPrefs_id);
+          element_addonPrefs.removeEventListener("popupshowing", this);
+          // Remove our entry.
+          let entry = window.document.getElementById(this.menu_addonPrefs_id + "_" + this.uniqueRandomID);
+          if (entry) entry.remove();
+          // Do we have to unhide the noPrefsElement?
+          if (element_addonPrefs.children.length == 1) {
+            let noPrefsElem = element_addonPrefs.querySelector('[disabled="true"]');
+            noPrefsElem.style.display = "inline";
+          }
+        } else {
+          // Remove event listener for addon manager view changes
+          let managerWindow = this.getAddonManagerFromWindow(window);
+          if (
+            managerWindow && 
+            managerWindow[this.uniqueRandomID] && 
+            managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners
+          ) {
+            managerWindow.document.removeEventListener("ViewChanged", this);
+            managerWindow.document.removeEventListener("update", this);
+            managerWindow.document.removeEventListener("view-loaded", this);
+            managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = false;
+
+            let cards = this.getCards(managerWindow);
+            if (getThunderbirdVersion().major < 88) {
+              // Remove options menu in 78-87
+              for (let card of cards) {
+                let addonOptionsLegacyEntry = card.querySelector(".extension-options-legacy");
+                if (addonOptionsLegacyEntry) addonOptionsLegacyEntry.remove();
+              }
+            } else {
+              // Remove options button in 88
+              for (let card of cards) {
+                if (card.addon.id == this.extension.id) {
+                  let addonOptionsButton = card.querySelector(".extension-options-button2");
+                  if (addonOptionsButton) addonOptionsButton.remove();
+                  break;
+                }
+              }
+            }
+          }
+
+          // Remove tabmonitor
+          if (window[this.uniqueRandomID].hasTabMonitor) {
+            this.getTabMail(window).unregisterTabMonitor(this.tabMonitor);
+            window[this.uniqueRandomID].hasTabMonitor = false;
+          }
+
+        }
+      }
+      // Stop listening for new windows.
+      ExtensionSupport.unregisterWindowListener("injectListener_" + this.uniqueRandomID);
+    }
+
+    // Execute registered shutdown()
+    try {
+      if (this.bootstrappedObj.shutdown) {
+        this.bootstrappedObj.shutdown(
+          this.extension.addonData,
+          isAppShutdown
+            ? this.BOOTSTRAP_REASONS.APP_SHUTDOWN
+            : this.BOOTSTRAP_REASONS.ADDON_DISABLE);
+      }
+    } catch (e) {
+      Components.utils.reportError(e)
+    }
+
+    if (this.resourceData) {
+      const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler);
+      for (let res of this.resourceData) {
+        // [ "resource", "shortname" , "path" ]
+        resProto.setSubstitution(
+          res[1],
+          null,
+        );
+      }
+    }
+
+    if (this.chromeHandle) {
+      this.chromeHandle.destruct();
+      this.chromeHandle = null;
+    }
+    // Flush all caches
+    Services.obs.notifyObservers(null, "startupcache-invalidate");
+    console.log("BootstrapLoader for " + this.extension.id + " unloaded!");
+  }
+};
+
+// Removed all extra code for backward compatibility for better maintainability.
+var BootstrapLoader_115 = class extends ExtensionCommon.ExtensionAPI {
+  getCards(e) {
+    // This gets triggered by real events but also manually by providing the outer window.
+    // The event is attached to the outer browser, get the inner one.
+    let doc = e.document || e.target;
+    return doc.querySelectorAll("addon-card");
+  }
+
+  // Event handler for the addon manager, to update the state of the options button.
+  handleEvent(e) {
+    switch (e.type) {
+      case "click": {
+        e.preventDefault();
+        e.stopPropagation();
+        let BL = {}
+        BL.extension = this.extension;
+        BL.messenger = getMessenger(this.context);
+        let w = Services.wm.getMostRecentWindow("mail:3pane");
+        w.openDialog(
+          this.pathToOptionsPage,
+          "AddonOptions",
+          "chrome,resizable,centerscreen",
+          BL
+        );
+      }
+        break;
+
+
+      // update, ViewChanged and manual call for add-on manager options overlay
+      default: {
+        let cards = this.getCards(e);
+        for (let card of cards) {
+          // Setup either the options entry in the menu or the button
+          if (card.addon.id == this.extension.id) {
+            // Add-on button
+            let addonOptionsButton = card.querySelector(
+              ".windowlistener-options-button"
+            );
+            if (card.addon.isActive && !addonOptionsButton) {
+              let origAddonOptionsButton = card.querySelector(".extension-options-button")
+              origAddonOptionsButton.setAttribute("hidden", "true");
+
+              addonOptionsButton = card.ownerDocument.createElement("button");
+              addonOptionsButton.classList.add("windowlistener-options-button");
+              addonOptionsButton.classList.add("extension-options-button");
+              card.optionsButton.parentNode.insertBefore(
+                addonOptionsButton,
+                card.optionsButton
+              );
+              card
+                .querySelector(".windowlistener-options-button")
+                .addEventListener("click", this);
+            } else if (!card.addon.isActive && addonOptionsButton) {
+              addonOptionsButton.remove();
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Some tab/add-on-manager related functions
+  getTabMail(window) {
+    return window.document.getElementById("tabmail");
+  }
+
+  // returns the outer browser, not the nested browser of the add-on manager
+  // events must be attached to the outer browser
+  getAddonManagerFromTab(tab) {
+    if (tab.browser && tab.mode.name == "contentTab") {
+      let win = tab.browser.contentWindow;
+      if (win && win.location.href == "about:addons") {
+        return win;
+      }
+    }
+  }
+
+  getAddonManagerFromWindow(window) {
+    let tabMail = this.getTabMail(window);
+    for (let tab of tabMail.tabInfo) {
+      let managerWindow = this.getAddonManagerFromTab(tab);
+      if (managerWindow) {
+        return managerWindow;
+      }
+    }
+  }
+
+  async getAddonManagerFromWindowWaitForLoad(window) {
+    let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane");
+
+    let tabMail = this.getTabMail(window);
+    for (let tab of tabMail.tabInfo) {
+      if (tab.browser && tab.mode.name == "contentTab") {
+        // Instead of registering a load observer, wait until its loaded. Not nice,
+        // but gets aroud a lot of edge cases.
+        while (!tab.pageLoaded) {
+          await new Promise(r => setTimeout(r, 150));
+        }
+        let managerWindow = this.getAddonManagerFromTab(tab);
+        if (managerWindow) {
+          return managerWindow;
+        }
+      }
+    }
+  }
+
+  setupAddonManager(managerWindow, forceLoad = false) {
+    if (!managerWindow) {
+      return;
+    }
+    if (!this.pathToOptionsPage) {
+      return;
+    }
+    if (
+      managerWindow &&
+      managerWindow[this.uniqueRandomID] &&
+      managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners
+    ) {
+      return;
+    }
+    
+    managerWindow.document.addEventListener("ViewChanged", this);
+    managerWindow.document.addEventListener("update", this);
+    managerWindow.document.addEventListener("view-loaded", this);
+    managerWindow[this.uniqueRandomID] = {};
+    managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = true;
+    if (forceLoad) {
+      this.handleEvent(managerWindow);
+    }
+  }
+
+  getAPI(context) {
+    this.uniqueRandomID = "AddOnNS" + context.extension.instanceId;
+    this.menu_addonPrefs_id = "addonPrefs";
+
+
+    this.pathToBootstrapScript = null;
+    this.pathToOptionsPage = null;
+    this.chromeHandle = null;
+    this.chromeData = null;
+    this.resourceData = null;
+    this.bootstrappedObj = {};
+
+    // make the extension object and the messenger object available inside
+    // the bootstrapped scope
+    this.bootstrappedObj.extension = context.extension;
+    this.bootstrappedObj.messenger = getMessenger(this.context);
+
+    this.BOOTSTRAP_REASONS = {
+      APP_STARTUP: 1,
+      APP_SHUTDOWN: 2,
+      ADDON_ENABLE: 3,
+      ADDON_DISABLE: 4,
+      ADDON_INSTALL: 5,
+      ADDON_UNINSTALL: 6, // not supported
+      ADDON_UPGRADE: 7,
+      ADDON_DOWNGRADE: 8,
+    };
+
+    const aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"].getService(Ci.amIAddonManagerStartup);
+    const resProto = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsISubstitutingProtocolHandler);
+
+    let self = this;
+
+    // TabMonitor to detect opening of tabs, to setup the options button in the add-on manager.
+    this.tabMonitor = {
+      onTabTitleChanged(tab) { },
+      onTabClosing(tab) { },
+      onTabPersist(tab) { },
+      onTabRestored(tab) { },
+      onTabSwitched(aNewTab, aOldTab) { },
+      async onTabOpened(tab) {
+        if (tab.browser && tab.mode.name == "contentTab") {
+          let { setTimeout } = Services.wm.getMostRecentWindow("mail:3pane");
+          // Instead of registering a load observer, wait until its loaded. Not nice,
+          // but gets aroud a lot of edge cases.
+          while (!tab.pageLoaded) {
+            await new Promise(r => setTimeout(r, 150));
+          }
+          self.setupAddonManager(self.getAddonManagerFromTab(tab));
         }
       },
     };
@@ -343,8 +722,8 @@
           let window = context.extension.windowManager.get(windowId, context).window
           let BL = {}
           BL.extension = self.extension;
-          BL.messenger = self.getMessenger(self.context);
-          window.openDialog(self.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL);        
+          BL.messenger = getMessenger(self.context);
+          window.openDialog(self.pathToOptionsPage, "AddonOptions", "chrome,resizable,centerscreen", BL);
         },
 
         registerChromeUrl(data) {
@@ -382,7 +761,7 @@
           self.resourceData = resourceData;
         },
 
-        registerBootstrapScript: async function(aPath) {
+        registerBootstrapScript: async function (aPath) {
           self.pathToBootstrapScript = aPath.startsWith("chrome://")
             ? aPath
             : context.extension.rootURI.resolve(aPath);
@@ -404,32 +783,30 @@
           } catch (e) {
             Components.utils.reportError(e)
           }
-          
+
           // Register window listener for main TB window
           if (self.pathToOptionsPage) {
             ExtensionSupport.registerWindowListener("injectListener_" + self.uniqueRandomID, {
               chromeURLs: [
                 "chrome://messenger/content/messenger.xul",
-                "chrome://messenger/content/messenger.xhtml",              
+                "chrome://messenger/content/messenger.xhtml",
               ],
               async onLoadWindow(window) {
-                if (self.getThunderbirdVersion().major < 78) {
+                if (getThunderbirdVersion().major < 78) {
                   let element_addonPrefs = window.document.getElementById(self.menu_addonPrefs_id);
                   element_addonPrefs.addEventListener("popupshowing", self);
                 } else {
-                  // Setup the options button/menu in the add-on manager, if it is already open.
-                  self.setupAddonManager(
-                    self.getAddonManagerFromWindow(window),
-                    true
-                  );
                   // Add a tabmonitor, to be able to setup the options button/menu in the add-on manager.
                   self.getTabMail(window).registerTabMonitor(self.tabMonitor);
                   window[self.uniqueRandomID] = {};
                   window[self.uniqueRandomID].hasTabMonitor = true;
+                  // Setup the options button/menu in the add-on manager, if it is already open.
+                  let managerWindow = await self.getAddonManagerFromWindowWaitForLoad(window);
+                  self.setupAddonManager(managerWindow, true);
                 }
               },
 
-              onUnloadWindow(window) {          
+              onUnloadWindow(window) {
               }
             });
           }
@@ -442,11 +819,11 @@
     if (isAppShutdown) {
       return; // the application gets unloaded anyway
     }
-    
+
     //remove our entry in the add-on options menu
     if (this.pathToOptionsPage) {
       for (let window of Services.wm.getEnumerator("mail:3pane")) {
-        if (this.getThunderbirdVersion().major < 78) {
+        if (getThunderbirdVersion().major < 78) {
           let element_addonPrefs = window.document.getElementById(this.menu_addonPrefs_id);
           element_addonPrefs.removeEventListener("popupshowing", this);
           // Remove our entry.
@@ -454,19 +831,24 @@
           if (entry) entry.remove();
           // Do we have to unhide the noPrefsElement?
           if (element_addonPrefs.children.length == 1) {
-              let noPrefsElem = element_addonPrefs.querySelector('[disabled="true"]');
-              noPrefsElem.style.display = "inline";
-          }              
+            let noPrefsElem = element_addonPrefs.querySelector('[disabled="true"]');
+            noPrefsElem.style.display = "inline";
+          }
         } else {
           // Remove event listener for addon manager view changes
           let managerWindow = this.getAddonManagerFromWindow(window);
-          if (managerWindow && managerWindow[this.uniqueRandomID] && managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners) {
+          if (
+            managerWindow && 
+            managerWindow[this.uniqueRandomID] && 
+            managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners
+          ) {
             managerWindow.document.removeEventListener("ViewChanged", this);
             managerWindow.document.removeEventListener("update", this);
             managerWindow.document.removeEventListener("view-loaded", this);
-            
+            managerWindow[this.uniqueRandomID].hasAddonManagerEventListeners = false;
+
             let cards = this.getCards(managerWindow);
-            if (this.getThunderbirdVersion().major < 88) {
+            if (getThunderbirdVersion().major < 88) {
               // Remove options menu in 78-87
               for (let card of cards) {
                 let addonOptionsLegacyEntry = card.querySelector(".extension-options-legacy");
@@ -483,13 +865,13 @@
               }
             }
           }
-          
+
           // Remove tabmonitor
           if (window[this.uniqueRandomID].hasTabMonitor) {
             this.getTabMail(window).unregisterTabMonitor(this.tabMonitor);
             window[this.uniqueRandomID].hasTabMonitor = false;
           }
-                    
+
         }
       }
       // Stop listening for new windows.
@@ -529,3 +911,7 @@
     console.log("BootstrapLoader for " + this.extension.id + " unloaded!");
   }
 };
+
+var BootstrapLoader = getThunderbirdVersion().major < 111
+  ? BootstrapLoader_102
+  : BootstrapLoader_115;
diff -Nru tbsync-4.3/content/api/BootstrapLoader/schema.json tbsync-4.7/content/api/BootstrapLoader/schema.json
--- tbsync-4.3/content/api/BootstrapLoader/schema.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/api/BootstrapLoader/schema.json	2023-08-29 22:22:49.000000000 +0200
@@ -35,7 +35,7 @@
             "type": "array",
             "items": {
               "type": "array",
-              "items" : {
+              "items": {
                 "type": "string"
               }
             },
@@ -58,4 +58,4 @@
       }
     ]
   }
-]
+]
\ Kein Zeilenumbruch am Dateiende.
diff -Nru tbsync-4.3/content/manager/accounts.js tbsync-4.7/content/manager/accounts.js
--- tbsync-4.3/content/manager/accounts.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/manager/accounts.js	2023-08-29 22:22:49.000000000 +0200
@@ -370,9 +370,9 @@
           
           //add icon (use "install provider" icon, if provider not installed)
           let itemType = document.createXULElement("image");
-          itemType.setAttribute("width", "16");
-          itemType.setAttribute("height", "16");
-          itemType.setAttribute("style", "margin: 0px 0px 0px 5px;");
+          //itemType.setAttribute("width", "16");
+          //itemType.setAttribute("height", "16");
+          itemType.setAttribute("style", "margin: 0px 0px 0px 5px; width:16px; height:16px");
           newListItem.appendChild(itemType);
 
           //add account name
@@ -382,9 +382,9 @@
 
           //add account status
           let itemStatus = document.createXULElement("image");
-          itemStatus.setAttribute("width", "16");
-          itemStatus.setAttribute("height", "16");
-          itemStatus.setAttribute("style", "margin: 0px 5px;");
+          //itemStatus.setAttribute("width", "16");
+          //itemStatus.setAttribute("height", "16");
+          itemStatus.setAttribute("style", "margin: 0px 5px; width:16px; height:16px");
           newListItem.appendChild(itemStatus);
           
           accountsList.appendChild(newListItem);
diff -Nru tbsync-4.3/content/manager/accounts.xhtml tbsync-4.7/content/manager/accounts.xhtml
--- tbsync-4.3/content/manager/accounts.xhtml	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/manager/accounts.xhtml	2023-08-29 22:22:49.000000000 +0200
@@ -45,9 +45,9 @@
             <richlistbox 
                 id="tbSyncAccounts.accounts"
                 flex="1"
-                style="margin: 0 1px"
+                style="margin: 0 1px; width: 200px;"
                 seltype="single"
-                context="tbsync.accountmanger.ContextMenu"                
+                context="tbsync.accountmanger.ContextMenu"
                 onkeypress="if (event.keyCode == 46) {tbSyncAccounts.deleteAccount();}"
                 onselect="tbSyncAccounts.loadSelectedAccount();">
                 <listheader style="border-bottom: 1px solid lightgrey;">
diff -Nru tbsync-4.3/content/manager/editAccount.js tbsync-4.7/content/manager/editAccount.js
--- tbsync-4.3/content/manager/editAccount.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/manager/editAccount.js	2023-08-29 22:22:49.000000000 +0200
@@ -9,7 +9,6 @@
  "use strict";
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { OS }  =ChromeUtils.import("resource://gre/modules/osfile.jsm");
 var { TbSync } = ChromeUtils.import("chrome://tbsync/content/tbsync.jsm");
 
 var tbSyncAccountSettings = {
@@ -104,7 +103,7 @@
     document.getElementById('tbsync.accountsettings.frame').hidden = false;	    
     tbSyncAccountSettings.updateFolderList();      
 
-    if (OS.Constants.Sys.Name == "Darwin") { //we might need to find a way to detect MacOS like styling, other themes move the header bar into the tabpanel as well
+    if (Services.appinfo.OS == "Darwin") { //we might need to find a way to detect MacOS like styling, other themes move the header bar into the tabpanel as well
       document.getElementById('manager.tabpanels').style["padding-top"] = "3ex";
     }
   },
diff -Nru tbsync-4.3/content/manager/editAccount.xhtml tbsync-4.7/content/manager/editAccount.xhtml
--- tbsync-4.3/content/manager/editAccount.xhtml	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/manager/editAccount.xhtml	2023-08-29 22:22:49.000000000 +0200
@@ -39,11 +39,11 @@
                     <label class="header" style="margin-left:0; margin-bottom:1ex;" value="__TBSYNCMSG_manager.tabs.status.general__" />
                     <checkbox id="tbsync.accountsettings.enabled" oncommand="tbSyncAccountSettings.toggleEnableState(this);" label="__TBSYNCMSG_manager.tabs.status.enableThisAccount__"  />
 
-                    <vbox class="showIfEnabled">
+                    <vbox class="showIfEnabled" style="height:100px; overflow-x: hidden; overflow-y:hidden">
                         <hbox flex="1">
                             <vbox flex="1">
                                 <label class="header" style="margin-left:0; margin-bottom:1ex; margin-top:2ex;" value="__TBSYNCMSG_manager.status__" />
-                                <description flex="1" id="syncstate"></description>
+                                <description id="syncstate"></description>
                             </vbox>
                             <vbox flex="0">
                                 <label class="header" style="margin-left:0; margin-bottom:1ex; margin-top:1ex; visibility: hidden" value="nix" />
@@ -58,8 +58,7 @@
                             <description>__TBSYNCMSG_manager.tabs.status.resources.intro__</description>
                             <richlistbox 
                               id="tbsync.accountsettings.folderlist"
-                              flex="1"
-                              style="margin: 0 1px 1px 1ex;padding:0;"
+                              style="margin: 0 1px 1px 1ex;padding:0; height:225px; overflow-x: hidden;"
                               context="tbsync.accountsettings.FolderListContextMenu"
                               seltype="single">
                                 <listheader id="tbsync.accountsettings.folderlist.header" style="border-bottom: 1px solid lightgrey;">
diff -Nru tbsync-4.3/content/manager/eventlog/eventlog.js tbsync-4.7/content/manager/eventlog/eventlog.js
--- tbsync-4.3/content/manager/eventlog/eventlog.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/manager/eventlog/eventlog.js	2023-08-29 22:22:49.000000000 +0200
@@ -25,12 +25,10 @@
       let item = tbSyncEventLog.addLogEntry(events[i]);
       eventlog.appendChild(item);
     }
-
     eventlog.hidden = false;
     eventlog.ensureIndexIsVisible(eventlog.getRowCount()-1);
-    document.documentElement.getButton("extra1").onclick = tbSyncEventLog.onclear;
-    document.documentElement.getButton("extra1").label = TbSync.getString("eventlog.clear");
-    document.documentElement.getButton("cancel").label = TbSync.getString("eventlog.close");
+    document.getElementById("tbsync.eventlog.clear").addEventListener("click", tbSyncEventLog.onclear);
+    document.getElementById("tbsync.eventlog.close").addEventListener("click", () => window.close());
   },
 
   onclear: function () {
@@ -71,7 +69,8 @@
     
     //left column
     let leftColumn = document.createXULElement("vbox");
-    leftColumn.setAttribute("width", "24");
+    //leftColumn.setAttribute("width", "24");
+    leftColumn.setAttribute("style", "width: 24px;");
 
     let image = document.createXULElement("image");
     let src = entry.type.endsWith("_rerun") ? "sync" : entry.type;
diff -Nru tbsync-4.3/content/manager/eventlog/eventlog.xhtml tbsync-4.7/content/manager/eventlog/eventlog.xhtml
--- tbsync-4.3/content/manager/eventlog/eventlog.xhtml	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/manager/eventlog/eventlog.xhtml	2023-08-29 22:22:49.000000000 +0200
@@ -1,11 +1,8 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 
-<dialog
-    width="600"
-    height="400"
+<window
     title="__TBSYNCMSG_eventlog.title__"
-    buttons="cancel, extra1"
     onload="tbSyncEventLog.onload();"
     onunload="tbSyncEventLog.onunload();"
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; >
@@ -14,6 +11,11 @@
     <script type="text/javascript" src="chrome://tbsync/content/scripts/locales.js" /> 
 
     <vbox flex="1">
-        <richlistbox id="tbsync.eventlog" flex="1" seltype="single" disabled="true"/>
+        <richlistbox id="tbsync.eventlog" style="padding:5px; height:360px" seltype="single" disabled="true"/>
+        <hbox style="padding: 5px">
+            <vbox flex="1"></vbox>
+            <button id="tbsync.eventlog.clear" label="__TBSYNCMSG_eventlog.clear__" />
+            <button id="tbsync.eventlog.close" label="__TBSYNCMSG_eventlog.close__" />
+        </hbox>
     </vbox>
-</dialog>
+</window>
diff -Nru tbsync-4.3/content/modules/db.js tbsync-4.7/content/modules/db.js
--- tbsync-4.3/content/modules/db.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/modules/db.js	2023-08-29 22:22:49.000000000 +0200
@@ -41,12 +41,11 @@
       this.files[f].write = new DeferredTask(() => this.writeAsync(f), 6000);
       
       try {
-        let data = await OS.File.read(TbSync.io.getAbsolutePath(this.files[f].name));
-        this[f] = JSON.parse(TbSync.decoder.decode(data));
+        this[f] = await IOUtils.readJSON(TbSync.io.getAbsolutePath(this.files[f].name));
         this.files[f].found = true;
       } catch (e) {
         //if there is no file, there is no file...
-        this[f] = JSON.parse(this.files[f].default);                
+        this[f] = JSON.parse(this.files[f].default);
         this.files[f].found = false;
         Components.utils.reportError(e);
       }
@@ -66,8 +65,7 @@
     // try to migrate old accounts file from TB60
     if (!this.files["accounts"].found) {
       try {
-        let data = await OS.File.read(TbSync.io.getAbsolutePath("accounts.json"));
-        let accounts = JSON.parse(TbSync.decoder.decode(data));
+        let accounts = await IOUtils.readJSON(TbSync.io.getAbsolutePath("accounts.json"));
         for (let d of Object.values(accounts.data)) {
           console.log("Migrating: " + JSON.stringify(d));
           
@@ -141,10 +139,7 @@
     }
     
     let filepath = TbSync.io.getAbsolutePath(this.files[f].name);
-    let json = TbSync.encoder.encode(JSON.stringify(this[f]));
-    
-    await OS.File.makeDir(TbSync.io.storageDirectory);
-    await OS.File.writeAtomic(filepath, json, {tmpPath: filepath + ".tmp"});
+    await IOUtils.writeJSON(filepath, this[f]);
   },
 
 
diff -Nru tbsync-4.3/content/modules/io.js tbsync-4.7/content/modules/io.js
--- tbsync-4.3/content/modules/io.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/modules/io.js	2023-08-29 22:22:49.000000000 +0200
@@ -10,7 +10,7 @@
  
 var io = {
 
-  storageDirectory : OS.Path.join(OS.Constants.Path.profileDir, "TbSync"),
+  storageDirectory : PathUtils.join(PathUtils.profileDir, "TbSync"),
 
   load: async function () {
   },
@@ -19,7 +19,7 @@
   },
 
   getAbsolutePath: function(filename) {
-    return OS.Path.join(this.storageDirectory, filename);
+    return PathUtils.join(this.storageDirectory, filename);
   },
   
   initFile: function (filename) {
diff -Nru tbsync-4.3/content/modules/lightning.js tbsync-4.7/content/modules/lightning.js
--- tbsync-4.3/content/modules/lightning.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/modules/lightning.js	2023-08-29 22:22:49.000000000 +0200
@@ -387,7 +387,7 @@
       if (pretagChangelogWithByServerEntry) {
         tbItem.changelogStatus = "added_by_server";
       }
-      return await this._calendar.adoptItem(tbItem._item);
+      return await this._calendar.addItem(tbItem._item);
     }
     
     async modifyItem(tbNewItem, tbOldItem, pretagChangelogWithByServerEntry = true) {
diff -Nru tbsync-4.3/content/modules/manager.js tbsync-4.7/content/modules/manager.js
--- tbsync-4.3/content/modules/manager.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/modules/manager.js	2023-08-29 22:22:49.000000000 +0200
@@ -236,7 +236,8 @@
     if (itemACL) itemHGroup1.appendChild(itemACL);
 
     let itemVGroup1 = document.createXULElement("vbox");
-    itemVGroup1.setAttribute("width", "93");
+    //itemVGroup1.setAttribute("width", "93");
+    itemVGroup1.setAttribute("style", "width: 93px");
     itemVGroup1.appendChild(itemHGroup1);
 
     //group2
@@ -246,8 +247,8 @@
     itemHGroup2.appendChild(itemLabel);
 
     let itemVGroup2 = document.createXULElement("vbox");
-    itemVGroup2.setAttribute("width", "150");
-    itemVGroup2.setAttribute("style", "padding: 3px");
+    //itemVGroup2.setAttribute("width", "150");
+    itemVGroup2.setAttribute("style", "padding: 3px; width: 150px");
     itemVGroup2.appendChild(itemHGroup2);
 
     //group3
@@ -256,8 +257,8 @@
     itemHGroup3.appendChild(itemStatus);
 
     let itemVGroup3 = document.createXULElement("vbox");
-    itemVGroup3.setAttribute("width", "250");
-    itemVGroup3.setAttribute("style", "padding: 3px");
+    //itemVGroup3.setAttribute("width", "250");
+    itemVGroup3.setAttribute("style", "padding: 3px; width: 250px");
     itemVGroup3.appendChild(itemHGroup3);
 
     //final row
diff -Nru tbsync-4.3/content/passwordPrompt/passwordPrompt.css tbsync-4.7/content/passwordPrompt/passwordPrompt.css
--- tbsync-4.3/content/passwordPrompt/passwordPrompt.css	1970-01-01 01:00:00.000000000 +0100
+++ tbsync-4.7/content/passwordPrompt/passwordPrompt.css	2023-08-29 22:22:49.000000000 +0200
@@ -0,0 +1,13 @@
+  .grid-container {
+    display: grid;
+    grid-template-columns: auto 1fr;
+    grid-template-rows: auto auto auto;
+    gap: 1px;
+    width: 250px;
+    margin: 2ex auto;
+  }
+
+  .grid-item {
+    padding: 2px;
+    text-align: left;
+  }
diff -Nru tbsync-4.3/content/passwordPrompt/passwordPrompt.js tbsync-4.7/content/passwordPrompt/passwordPrompt.js
--- tbsync-4.3/content/passwordPrompt/passwordPrompt.js	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/passwordPrompt/passwordPrompt.js	2023-08-29 22:22:49.000000000 +0200
@@ -23,19 +23,21 @@
     this.userfield.value = data.username;
     this.userfield.disabled = data.usernameLocked;
 
-    document.addEventListener("dialogaccept",  tbSyncPassword.doOK.bind(this));
     window.addEventListener("unload", tbSyncPassword.doCANCEL.bind(this));
     document.getElementById("tbsync.password").focus();
+    document.getElementById("tbsync.password.ok").addEventListener("click", tbSyncPassword.doOK.bind(this));
+    document.getElementById("tbsync.password.cancel").addEventListener("click", () => window.close());
   },
 
-  doOK: function (event) {        
+  doOK: function (event) {
     if (!this.resolved) {
       this.resolved = true
       this.resolve({username: this.userfield.value, password: this.passfield.value});
+      window.close();
     }
   },
   
-  doCANCEL: function (event) {        
+  doCANCEL: function (event) {
     if (!this.resolved) {
       this.resolved = true
       this.resolve(false);
diff -Nru tbsync-4.3/content/passwordPrompt/passwordPrompt.xhtml tbsync-4.7/content/passwordPrompt/passwordPrompt.xhtml
--- tbsync-4.3/content/passwordPrompt/passwordPrompt.xhtml	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/passwordPrompt/passwordPrompt.xhtml	2023-08-29 22:22:49.000000000 +0200
@@ -1,38 +1,32 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="chrome://tbsync/content/passwordPrompt/passwordPrompt.css" type="text/css"?>
 
-<dialog
+<window
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     xmlns:html="http://www.w3.org/1999/xhtml";
     title="__TBSYNCMSG_password.title__"
-    buttons="accept,cancel"
     onload="tbSyncPassword.onload();">
 
     <script type="application/javascript" src="chrome://tbsync/content/passwordPrompt/passwordPrompt.js"/>
     <script type="text/javascript" src="chrome://tbsync/content/scripts/locales.js" /> 
 
-    <vbox>
-        <description style="width: 350px;">__TBSYNCMSG_password.description__</description>
-        <grid style="margin:1ex;">
-            <columns>
-                <column flex="0"/>
-                <column flex="1"/>
-            </columns>
-            <rows>
-                <row style="margin-bottom:1ex;">
-                    <label value="__TBSYNCMSG_password.account__"/>
-                    <label class="header"  id="tbsync.account" />
-                </row>
-                <row align="center">
-                    <label value="__TBSYNCMSG_password.user__"/>
-                    <html:input id="tbsync.user" />
-                </row>
-                <row align="center">
-                    <label value="__TBSYNCMSG_password.password__"/>
-                    <html:input type="password" id="tbsync.password"/>
-                </row>
-            </rows>
-        </grid>
+    <vbox flex="1">
+        <description style="padding: 5px; width: 350px;">__TBSYNCMSG_password.description__</description>
+
+        <html:div class="grid-container">
+            <html:div class="grid-item"><label value="__TBSYNCMSG_password.account__"/></html:div>
+            <html:div class="grid-item"><label class="header"  id="tbsync.account" /></html:div>
+            <html:div class="grid-item"><label value="__TBSYNCMSG_password.user__"/></html:div>
+            <html:div class="grid-item"><html:input id="tbsync.user" /></html:div>
+            <html:div class="grid-item"><label value="__TBSYNCMSG_password.password__"/></html:div>
+            <html:div class="grid-item"><html:input type="password" id="tbsync.password"/></html:div>
+        </html:div>
+        <hbox style="padding: 5px">
+            <vbox flex="1"></vbox>
+            <button id="tbsync.password.ok" label="__TBSYNCMSG_password.ok__" />
+            <button id="tbsync.password.cancel" label="__TBSYNCMSG_password.cancel__" />
+        </hbox>
     </vbox>
 
-</dialog>
+</window>
diff -Nru tbsync-4.3/content/tbsync.jsm tbsync-4.7/content/tbsync.jsm
--- tbsync-4.3/content/tbsync.jsm	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/content/tbsync.jsm	2023-08-29 22:22:49.000000000 +0200
@@ -12,7 +12,6 @@
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { FileUtils } = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
-var { OS }  =ChromeUtils.import("resource://gre/modules/osfile.jsm");
 var { AddonManager } = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
 var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 var { MailServices } = ChromeUtils.import("resource:///modules/MailServices.jsm");
@@ -53,7 +52,7 @@
     this.dump("TbSync init","Start (" + this.addon.version.toString() + ")");
 
     //print information about Thunderbird version and OS
-    this.dump(Services.appinfo.name, Services.appinfo.version + " on " + OS.Constants.Sys.Name);
+    this.dump(Services.appinfo.name, Services.appinfo.version + " on " + Services.appinfo.OS);
 
     // register modules to be used by TbSync
     this.modules.push({name: "db", state: 0});
diff -Nru tbsync-4.3/debian/changelog tbsync-4.7/debian/changelog
--- tbsync-4.3/debian/changelog	2022-10-14 13:32:30.000000000 +0200
+++ tbsync-4.7/debian/changelog	2023-10-14 09:22:21.000000000 +0200
@@ -1,3 +1,29 @@
+tbsync (4.7-1~deb12u1) bookworm; urgency=medium
+
+  [ Mechtilde ]
+  * [f9e272f] Adjust version of dependencies
+  * Prepared for release in bookworm (proposed-updates)
+
+ -- Mechtilde Stehmann <mechti...@debian.org>  Sat, 14 Oct 2023 09:22:21 +0200
+
+tbsync (4.7-1) unstable; urgency=medium
+
+  [ Mechtilde ]
+  * [c727b2e] New upstream version 4.7
+  * [3187154] Compression is now tar.gz
+
+ -- Mechtilde Stehmann <mechti...@debian.org>  Tue, 12 Sep 2023 19:31:30 +0200
+
+tbsync (4.3+git20230524+9459652-1) experimental; urgency=medium
+
+  [ Mechtilde ]
+  * [70d9fd8] New upstream version 4.3+git20230524+9459652
+              Made it fit for thunderbird 115.*
+  * [70d9fd8] New upstream version 4.3+git20230524+9459652
+  * [6321440] Changed coompression for zip file
+
+ -- Mechtilde Stehmann <mechti...@debian.org>  Wed, 26 Jul 2023 18:08:25 +0200
+
 tbsync (4.3-1) unstable; urgency=medium
 
   [ Mechtilde ]
diff -Nru tbsync-4.3/debian/control tbsync-4.7/debian/control
--- tbsync-4.3/debian/control	2022-09-22 19:40:48.000000000 +0200
+++ tbsync-4.7/debian/control	2023-10-11 20:36:34.000000000 +0200
@@ -13,9 +13,9 @@
 Package: webext-tbsync
 Architecture: all
 Depends: ${misc:Depends}
- , thunderbird (>= 1:102.2)
-Recommends: webext-dav4tbsync (>= 4.0)
- , webext-eas4tbsync (>= 2.0)
+ , thunderbird (>= 1:115.3)
+Recommends: webext-dav4tbsync (>= 4.7)
+ , webext-eas4tbsync (>= 4.7)
 Description: Thunderbird/Lightning Add-On to support MS Exchange Calendar etc.
  Synchronize Exchange ActiveSync accounts (contacts, tasks and
  calendars) to Thunderbird, supports Office 365, Outlook.com,
diff -Nru tbsync-4.3/debian/gbp.conf tbsync-4.7/debian/gbp.conf
--- tbsync-4.3/debian/gbp.conf	2022-04-17 13:18:05.000000000 +0200
+++ tbsync-4.7/debian/gbp.conf	2023-09-12 19:11:02.000000000 +0200
@@ -4,7 +4,7 @@
 # use pristine-tar:
 pristine-tar = True
 # generate gz compressed orig file
-compression = gz
+# compression = xz
 debian-branch = debian/sid
 upstream-branch = upstream
 
diff -Nru tbsync-4.3/_locales/bg/messages.json tbsync-4.7/_locales/bg/messages.json
--- tbsync-4.3/_locales/bg/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/bg/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Синхронизирай информацията от всички TbSync регистрации със сървърите"
+    },
+    "password.ok": {
+        "message": "ОК"
+    },
+    "password.cancel": {
+        "message": "Отказ"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/cs/messages.json tbsync-4.7/_locales/cs/messages.json
--- tbsync-4.3/_locales/cs/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/cs/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronizovat poslední změny"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Zrušit"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/de/messages.json tbsync-4.7/_locales/de/messages.json
--- tbsync-4.3/_locales/de/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/de/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -3,28 +3,28 @@
         "message": "Um diesen Fehler zu beheben, können Sie einen Fehlerbericht an den Entwickler von TbSync schicken. Soll der Fehlerbericht jetzt angefertigt werden?"
     },
     "NoDebugLog": {
-        "message": "Es liegen keine aussagekräftigen Debug-Meldungen vor. Bitte aktivieren Sie den Debug-Modus, starten Thunderbird neu und wiederholen dann alle Schritte um das fehlerhafte Verhalten zu reproduzieren."
+        "message": "Es liegen keine aussagekräftigen Debug-Meldungen vor. Bitte aktivieren Sie den Debug-Modus, starten Thunderbird neu und wiederholen dann alle Schritte, um das fehlerhafte Verhalten zu reproduzieren."
     },
     "OopsMessage": {
-        "message": "Oops! TbSync konnte nicht starten!"
+        "message": "Hoppla! TbSync konnte nicht starten!"
     },
     "RestartThunderbirdAndTryAgain": {
-        "message": "Der TbSync Debug-Modus wurde aktiviert, bitte starten Sie Thunderbird neu und versuchen Sie dann noch einmal TbSync zu öffnen."
+        "message": "Das TbSync-Debug-Protokoll wurde eingeschaltet. Bitte starten Sie Thunderbird neu, und versuchen Sie dann noch einmal, TbSync zu öffnen!"
     },
     "UnableToTraceError": {
-        "message": "Es ist im Augenblick nicht möglich, diesen Fehler zu untersuchen, da der TbSync Debug-Modus nicht aktiviert ist. Soll der Debug-Modus aktiviert werden, damit dieser Fehler untersucht und behoben werden kann?"
+        "message": "Dieser Fehler kann nicht untersucht werden, solange das Debug-Protokoll deaktiviert ist. Soll das Protokoll jetzt aktiviert werden, damit dieser Fehler untersucht und behoben werden kann?"
     },
     "accountacctions.delete": {
-        "message": "Konto '##accountname##' löschen"
+        "message": "Konto „##accountname##” löschen"
     },
     "accountacctions.disable": {
         "message": "Konto '##accountname##' deaktivieren"
     },
     "accountacctions.enable": {
-        "message": "Konto '##accountname##' aktivieren & Server kontaktieren"
+        "message": "Konto „##accountname##” aktivieren und Server kontaktieren"
     },
     "accountacctions.sync": {
-        "message": "Konto '##accountname##' synchronisieren"
+        "message": "Konto „##accountname##” synchronisieren"
     },
     "addressbook.searchall": {
         "message": "Alle Adressbücher durchsuchen"
@@ -60,25 +60,25 @@
         "message": "Leerlauf"
     },
     "installProvider.header": {
-        "message": "Provider '##replace.1##' für TbSync ist noch nicht installiert."
+        "message": "Provider „##replace.1##” für TbSync ist noch nicht installiert."
     },
     "manager.AccountActions": {
-        "message": "Konto Aktionen"
+        "message": "Konto-Aktionen"
     },
     "manager.AddAccount": {
-        "message": "Neues Konto hinzufügen"
+        "message": "Konto hinzufügen"
     },
     "manager.DeleteAccount": {
-        "message": "Konto löschen"
+        "message": "Konto entfernen"
     },
     "manager.DisableAccount": {
         "message": "Konto deaktivieren"
     },
     "manager.EnableAccount": {
-        "message": "Konto aktivieren & mit dem Server verbinden"
+        "message": "Konto aktivieren und mit dem Server verbinden"
     },
     "manager.RetryConnectAccount": {
-        "message": "Erneut versuchen mit dem Server zu verbinden"
+        "message": "Erneut versuchen, mit dem Server zu verbinden"
     },
     "manager.ShowEventLog": {
         "message": "Ereignisprotokoll anzeigen"
@@ -96,10 +96,10 @@
         "message": "Kontoeinstellungen"
     },
     "manager.catman.text": {
-        "message": "TbSync synchronisiert auch Kontaktkategorien, die einen effizienten Ersatz für die nicht synchronisierbaren Kontaktlisten darstellen. Um diese im Thunderbird Adressbuch zu nutzen, können Sie das Add-On 'Category Manager' installieren. Dieses Add-On ermöglicht die Verwaltung überlappender kategoriebasierter Kontaktgruppen und stellt eine Reihe anderer kategoriespezifischer Funktionen bereit. Es kann aus dem offiziellen Mozilla Add-On Repository heruntergeladen werden:"
+        "message": "TbSync synchronisiert auch Kontaktkategorien, die einen effizienten Ersatz für die nicht synchronisierbaren Kontaktlisten darstellen. Um diese im Thunderbird-Adressbuch zu nutzen, können Sie das Add-On „Category Manager” installieren. Dieses Add-On ermöglicht die Verwaltung überlappender kategoriebasierter Kontaktgruppen und stellt eine Reihe anderer kategoriespezifischer Funktionen bereit. Es kann aus dem offiziellen Mozilla Add-On Repository heruntergeladen werden:"
     },
     "manager.community": {
-        "message": "Community"
+        "message": "Nutzergemeinschaft"
     },
     "manager.connecting": {
         "message": "Verbindung wird hergestellt"
@@ -120,7 +120,7 @@
         "message": "Aktiviert: Protokolliert alle Fehler"
     },
     "manager.help.debuglevel.2": {
-        "message": "Aktiviert: Protokolliert alle gesendeten & empfangenen Daten"
+        "message": "Aktiviert: Protokolliert alle gesendeten und empfangenen Daten"
     },
     "manager.help.debuglevel.3": {
         "message": "Aktiviert: Protokolliert alle Daten und einige interne Debug-Werte"
@@ -138,25 +138,25 @@
         "message": "Benötigen Sie Hilfe?"
     },
     "manager.help.viewdebuglog": {
-        "message": "Debug-Log anzeigen"
+        "message": "Debug-Protokoll anzeigen"
     },
     "manager.help.wiki": {
-        "message": "Besuchen Sie die Wikiseiten des TbSync Projektes, diese beinhalten zusätzliche Informationen, Benutzeranleitungen und detaillierte Konfigurationsbeschreibungen."
+        "message": "Besuchen Sie die Wikiseiten des TbSync-Projekts, diese enthalten zusätzliche Informationen, Benutzeranleitungen und detaillierte Konfigurationsbeschreibungen."
     },
     "manager.installprovider.link": {
-        "message": "Klicken Sie auf den folgenden Link, um die Informationsseite des fehlenden Provider aufzurufen. Auf dieser Seite finden Sie weitere Informationen zu dem Provider und haben die Möglichkeit, diesen zu installieren:"
+        "message": "Klicken Sie auf den folgenden Link, um die Informationsseite des fehlenden Synchronisations-Providers aufzurufen. Dort finden Sie weitere Informationen dazu und haben die Möglichkeit, diesen zu installieren:"
     },
     "manager.installprovider.warning": {
-        "message": "Dieser Provider stammt nicht aus dem offiziellen Thunderbird Add-On Verzeichnis und wurde demnach nicht von Thunderbird-Mitarbeitern überprüft. Dieser Provider könnte schlimme Dinge mit Ihrem System anstellen. Benutzung auf eigene Gefahr."
+        "message": "Dieser Provider stammt nicht aus der offiziellen Thunderbird-Add-On-Sammlung und wurde demnach nicht von Thunderbird-Mitarbeitern überprüft. Es könnte sich um Schad-Software handeln, deshalb verwenden Sie es auf eigene Gefahr."
     },
     "manager.lockedsettings.description": {
         "message": "Um Synchronisierungsfehler zu vermeiden, können einige Einstellungen nicht bearbeitet werden, während das Konto aktiviert ist."
     },
     "manager.missingprovider": {
-        "message": "Dieses Konto benötigt den ##provider## Synchronisationsprovider, der zur Zeit aber nicht installiert ist."
+        "message": "Dieses Konto benötigt den ##provider##-Synchronisations-Provider, noch nicht installiert ist."
     },
     "manager.noaccounts": {
-        "message": "Es sind aktuell noch keine Konten konfiguriert."
+        "message": "Es sind noch keine Konten definiert."
     },
     "manager.provider": {
         "message": "Provider installieren"
@@ -174,13 +174,13 @@
         "message": "Status"
     },
     "manager.supporter.contributors": {
-        "message": "Mitwirkende & Übersetzer"
+        "message": "Mitwirkende und Übersetzer"
     },
     "manager.supporter.details": {
         "message": "Details"
     },
     "manager.supporter.sponsors": {
-        "message": "Sponsoren von Test-Accounts"
+        "message": "Sponsoren von Testkonten"
     },
     "manager.tabs.status": {
         "message": "Synchronisationsstatus"
@@ -195,7 +195,7 @@
         "message": "Allgemein"
     },
     "manager.tabs.status.never": {
-        "message": "Eine Einstellung von 0 deaktiviert periodische Synchronisation. Push Synchronisation wird noch nicht unterstützt."
+        "message": "Eine Einstellung von 0 deaktiviert periodische Synchronisation. Push-Synchronisation wird noch nicht unterstützt."
     },
     "manager.tabs.status.resources": {
         "message": "Verfügbare Ressourcen"
@@ -207,13 +207,13 @@
         "message": "Jetzt synchronisieren"
     },
     "manager.tabs.status.tryagain": {
-        "message": "Erneut versuchen mit dem Server zu verbinden"
+        "message": "Erneut versuchen, mit dem Server zu verbinden"
     },
     "manager.title": {
         "message": "TbSync Kontoverwaltung"
     },
     "manager.tryagain": {
-        "message": "Erneut versuchen mit dem Server zu verbinden"
+        "message": "Erneut versuchen, mit dem Server zu verbinden"
     },
     "menu.settingslabel": {
         "message": "Synchronisationseinstellungen (TbSync)"
@@ -228,13 +228,13 @@
         "message": "Passwort:"
     },
     "password.title": {
-        "message": "TbSync Anmeldeinformationen"
+        "message": "TbSync-Anmeldeinformationen"
     },
     "password.user": {
-        "message": "Benutzer:"
+        "message": "Nutzer:"
     },
     "popup.opensettings": {
-        "message": "TbSync Kontoverwaltung öffnen"
+        "message": "TbSync-Kontoverwaltung öffnen"
     },
     "prompt.DeleteAccount": {
         "message": "Sind Sie sicher, dass Sie das Konto ##accountName## löschen möchten?"
@@ -243,37 +243,37 @@
         "message": "Sind Sie sicher, dass Sie dieses Konto deaktivieren möchten? Alle lokalen Veränderungen, die noch nicht synchronisiert wurden, gehen dabei verloren!"
     },
     "prompt.Erase": {
-        "message": "Sind Sie sicher, dass Sie dieses Konto eines unbekannten Providers aus der Kontoliste entfernen möchten?"
+        "message": "Sind Sie sicher, dass Sie dieses Konto eines unbekannten Anbieters aus der Kontoliste entfernen möchten?"
     },
     "prompt.Unsubscribe": {
         "message": "Sind Sie sicher, dass Sie dieses Element nicht länger abonnieren möchten? Alle lokalen Veränderungen, die noch nicht synchronisiert wurden, gehen dabei verloren!"
     },
     "status.JavaScriptError": {
-        "message": "Javascript Fehler! Bitte prüfen Sie das Ereignisprotokoll für weitere Details."
+        "message": "Javascript-Fehler! Bitte prüfen Sie das Ereignisprotokoll für weitere Details!"
     },
     "status.OAuthAbortError": {
-        "message": "OAuth 2.0 Authentifizierungsprozess vom Benutzer abgebrochen."
+        "message": "OAuth 2.0-Authentifizierungsprozess vom Nutzer abgebrochen."
     },
     "status.OAuthHttpError": {
-        "message": "OAuth 2.0 Authentifizierungsprozess fehlgeschlagen (HTTP Error ##replace.1##)."
+        "message": "OAuth-2.0-Authentifizierungsprozess fehlgeschlagen (HTTP Error ##replace.1##)."
     },
     "status.OAuthNetworkError": {
-        "message": "Verbindung zum OAuth 2.0 Authentifizierungsserver nicht möglich."
+        "message": "Verbindung zum OAuth-2.0-Authentifizierungsserver nicht möglich."
     },
     "status.OAuthServerError": {
-        "message": " OAuth 2.0 Authentifizierungsserver meldet: ##replace.1##"
+        "message": " OAuth-2.0-Authentifizierungsserver meldet: ##replace.1##"
     },
     "status.aborted": {
         "message": "Nicht synchronisiert"
     },
     "status.apiError": {
-        "message": "API Implementierungsfehler"
+        "message": "API-Implementierungsfehler"
     },
     "status.disabled": {
         "message": "Konto ist deaktiviert, Synchronisation ist ausgeschaltet."
     },
     "status.foldererror": {
-        "message": "Bei mindestens einer Resource trat ein Synchronisationsfehler auf. Bitte prüfen sie das Ereignisprotokoll für weitere Details."
+        "message": "Bei mindestens einer Ressource trat ein Synchronisationsfehler auf. Bitte prüfen Sie das Ereignisprotokoll für weitere Details!"
     },
     "status.modified": {
         "message": "Lokale Änderungen"
@@ -282,10 +282,10 @@
         "message": "Verbindung zum Server fehlgeschlagen (##replace.1##)."
     },
     "status.no-folders-found-on-server": {
-        "message": "Auf dem Server wurden keine Resourcen gefunden."
+        "message": "Auf dem Server wurden keine Ressourcen gefunden."
     },
     "status.notargets": {
-        "message": "Synchronisation abgebrochen da die Elemente zum Synchronisieren nicht erstellt werden konnten."
+        "message": "Synchronisation abgebrochen, da die Elemente zum Synchronisieren nicht erstellt werden konnten."
     },
     "status.notsyncronized": {
         "message": "Konto muss synchronisiert werden."
@@ -294,7 +294,7 @@
         "message": "Warten auf Synchronisation"
     },
     "status.security": {
-        "message": "Fehler beim Aufbau einer sicherern Verbindung. Benutzen Sie eventuell ein selbst signiertes Zertifikat oder ein andersartiges nicht vertrauenswürdiges Zertifikat welches nicht in Thunderbird importiert ist? (##replace.1##)"
+        "message": "Fehler beim Aufbau einer sicheren Verbindung. Benutzen Sie eventuell ein selbst signiertes oder anderweitig nicht vertrauenswürdiges Zertifikat, das nicht in Thunderbird importiert ist? (##replace.1##)"
     },
     "status.skipped": {
         "message": "Nicht unterstützt"
@@ -354,6 +354,12 @@
         "message": "Synchronisiere alle TbSync Konten"
     },
     "toolbar.tooltiptext": {
-        "message": "Gleiche alle TbSync Konten mit den Servern ab"
+        "message": "Gleiche alle TbSync-Konten mit den Servern ab"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Abbrechen"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/en-US/messages.json tbsync-4.7/_locales/en-US/messages.json
--- tbsync-4.3/_locales/en-US/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/en-US/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronize latest changes"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Cancel"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/es/messages.json tbsync-4.7/_locales/es/messages.json
--- tbsync-4.3/_locales/es/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/es/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Sincronizar los últimos cambios"
+    },
+    "password.ok": {
+        "message": "Aceptar"
+    },
+    "password.cancel": {
+        "message": "Cancelar"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/et/messages.json tbsync-4.7/_locales/et/messages.json
--- tbsync-4.3/_locales/et/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/et/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronize latest changes"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Tühista"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/fr/messages.json tbsync-4.7/_locales/fr/messages.json
--- tbsync-4.3/_locales/fr/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/fr/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchroniser les dernières modifications"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Annuler"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/gl/messages.json tbsync-4.7/_locales/gl/messages.json
--- tbsync-4.3/_locales/gl/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/gl/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -141,7 +141,7 @@
         "message": "Ver rexistro de depuración"
     },
     "manager.help.wiki": {
-        "message": "Abrir as páxinas wiki do proxecto TbSync nas que facilitan información adicional, guías e descricións detalladas da configuración."
+        "message": "Abre o wiki do proxecto TbSync no que se facilita información adicional, guías e descricións detalladas da configuración."
     },
     "manager.installprovider.link": {
         "message": "Preme no seguinte enlace para abrir a páxina de información do provedor de sincronización que falta. Aí atoparás máis información sobre o provedor e terás a opción de instalalo:"
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Sincronizar os últimos cambios"
+    },
+    "password.ok": {
+        "message": "Aceptar"
+    },
+    "password.cancel": {
+        "message": "Cancelar"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/hu/messages.json tbsync-4.7/_locales/hu/messages.json
--- tbsync-4.3/_locales/hu/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/hu/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "A legújabb változtatások szinkronizálása"
+    },
+    "password.ok": {
+        "message": "Rendben"
+    },
+    "password.cancel": {
+        "message": "Mégse"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/it/messages.json tbsync-4.7/_locales/it/messages.json
--- tbsync-4.3/_locales/it/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/it/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Sincronizza le ultime modifiche"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Annulla"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/ja/messages.json tbsync-4.7/_locales/ja/messages.json
--- tbsync-4.3/_locales/ja/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/ja/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "最新の変更を同期"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "キャンセル"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/ko/messages.json tbsync-4.7/_locales/ko/messages.json
--- tbsync-4.3/_locales/ko/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/ko/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronize latest changes"
+    },
+    "password.ok": {
+        "message": "확인"
+    },
+    "password.cancel": {
+        "message": "취소"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/pl/messages.json tbsync-4.7/_locales/pl/messages.json
--- tbsync-4.3/_locales/pl/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/pl/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronizuj najnowsze zmiany"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Anuluj"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/pt_BR/messages.json tbsync-4.7/_locales/pt_BR/messages.json
--- tbsync-4.3/_locales/pt_BR/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/pt_BR/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Sincronizar as alterações mais recentes"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Cancelar"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/ro/messages.json tbsync-4.7/_locales/ro/messages.json
--- tbsync-4.3/_locales/ro/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/ro/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronize latest changes"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Anulare"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/ru/messages.json tbsync-4.7/_locales/ru/messages.json
--- tbsync-4.3/_locales/ru/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/ru/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Синхронизировать последние изменения"
+    },
+    "password.ok": {
+        "message": "ОК"
+    },
+    "password.cancel": {
+        "message": "Отмена"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/_locales/sv/messages.json tbsync-4.7/_locales/sv/messages.json
--- tbsync-4.3/_locales/sv/messages.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/_locales/sv/messages.json	2023-08-29 22:22:49.000000000 +0200
@@ -355,5 +355,11 @@
     },
     "toolbar.tooltiptext": {
         "message": "Synchronize latest changes"
+    },
+    "password.ok": {
+        "message": "OK"
+    },
+    "password.cancel": {
+        "message": "Avbryt"
     }
-}
\ Kein Zeilenumbruch am Dateiende.
+}
diff -Nru tbsync-4.3/manifest.json tbsync-4.7/manifest.json
--- tbsync-4.3/manifest.json	2022-10-12 21:40:25.000000000 +0200
+++ tbsync-4.7/manifest.json	2023-08-29 22:22:49.000000000 +0200
@@ -3,12 +3,12 @@
     "gecko": {
       "id": "tbs...@jobisoft.de",
       "strict_min_version": "102.3.0",
-      "strict_max_version": "102.*"
+      "strict_max_version": "115.*"
     }
   },
   "manifest_version": 2,
   "name": "TbSync",
-  "version": "4.3",
+  "version": "4.7",
   "author": "John Bieling",
   "homepage_url": "https://github.com/jobisoft/TbSync";,
   "default_locale": "en-US",

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to